From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Wed, 15 Apr 2026 17:28:34 -0700 Received: from mail-oi1-f192.google.com ([209.85.167.192]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wDAav-0004HT-4y for bitcoindev@gnusha.org; Wed, 15 Apr 2026 17:28:33 -0700 Received: by mail-oi1-f192.google.com with SMTP id 5614622812f47-464a0af43desf12041223b6e.3 for ; Wed, 15 Apr 2026 17:28:32 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1776299307; cv=pass; d=google.com; s=arc-20240605; b=b31CGAF7dMy4XBXYQhqVRrosUNGPTTo76Na7QJErfnDBpbQsaimVVKElr2ZmFVqRNE C/7svRhUeB67mpk6AT9x8fJ20EcH1NbGWc1zn0mKwylMBanmGKV6PczCceoTTzEoHgYC dU23KTWqtMgFX46wgnfkOo2Ata/qaEhBHfd5nWlx+JPPIPCkZrDWxZ+wnTuEpUA9Mdht oWNo2DAtiZjbsx1BIHXimq/UfNFNnHD9r7eUZ30wVKjdbAE8W6KcTX5r8pjThQWH8fC8 QlXZ/kSzUvQU5JVDjJW2cNZ9DQ5V7wSQb6YaMydPHdY2bpM4ThV/j7Y1CnYVzUa1S43p 7Ebw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:thread-index:content-language :content-transfer-encoding:mime-version:message-id:date:subject :in-reply-to:references:to:from:sender:dkim-signature; bh=Zc5m864K0jirjZk4vuOVUpM+kfHQ+Pw1m1gStQJ46n8=; fh=au7QEUMxRdzb/Mpx0ZVys5Vt4spihr2K2AerutW0T5c=; b=YR7Fvp3eJi0QtGIZaT1DfX2Z3BuTC8Dxgtyua4Yh0pMRInzYWSlcgYXkWdxhS/aIUT t9D6qK51g3N07cKuKAH+9yeSaOkccj48QaNdi+A6H1Y9g0wh0S+dWPnokTFm/z8SWJ/O OVuBodIIffTJdUmt/zhuUscGGIl75EzcT6FA/gDllC/VNZ8jwKFlvt2pmHooKI0xsXHv mKeeam8DrBfvYnsuU71JQJhZqM4IClQ6IfWI9VyZADULUkV+EySIRi5PppOIQdNb7moT YlvAF3pS0rF1hpW9kUDpI8Ftsy1qm/DueMGzq8ivODI7Tlz+8CPreZLm+YZjmkaDrp0u v+uw==; darn=gnusha.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@voskuil.org header.s=google header.b=MaqOFiZ8; spf=pass (google.com: domain of eric@voskuil.org designates 2607:f8b0:4864:20::82b as permitted sender) smtp.mailfrom=eric@voskuil.org; dara=pass header.i=@googlegroups.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1776299307; x=1776904107; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:thread-index:content-language :content-transfer-encoding:mime-version:message-id:date:subject :in-reply-to:references:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Zc5m864K0jirjZk4vuOVUpM+kfHQ+Pw1m1gStQJ46n8=; b=IlllMB08+ZCknASmwkoh7UH+vqfWyAAKrcoNNAgdXvKkkVYhlX5VgfM58pLMOUDzGE hsWftApDYU7+bQgwF6oa8B46Q9YsD/omfCq/52tNpIF6U2oSmTEHk+kUBQVgkrnZbAIJ AGcx1GuSIoOyd5TrN6TZwj/FYBIz5OVjom2Qze+Xt+oe1rUvmtzPJB3DVGBFJp+W5u9T pTRNPeY3XOF7vCtyrc5p9v343y6K0Ixzbu12En9A6glz3tyLiIE6Mr6JXWmgbPmZOqYw ZZn2hGag/UDFTmM7VnBvY8UcjisFQECvIPI9vc7d/RZB2/aVS91pzoeRM71UhCVvPTB6 b3gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776299307; x=1776904107; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:thread-index:content-language :content-transfer-encoding:mime-version:message-id:date:subject :in-reply-to:references:to:from:x-gm-gg:x-beenthere :x-gm-message-state:sender:from:to:cc:subject:date:message-id :reply-to; bh=Zc5m864K0jirjZk4vuOVUpM+kfHQ+Pw1m1gStQJ46n8=; b=Ntw/neewp0Nm/Pwfoyt7bp8ESYwU1Pep5W6vS0ukKI+G203L5/6IxBr3+Ng56U4ZaG tOe1x6QSZRm7Uh9tUrN/WUS6JpcQJEXgec7XkUuQZjPcAzTvytLthfINkTMGtB1RHdFX 8qXjBGaBGy9aASpQzSXuwJPo7LdCLqpSDXrgNtYIosmEaAW0wnWeQ2JD5AwspomMmjxr nNNKBZVimCaF6eEObSSZQHP7FgFsbTt9cx69eT9c9B9cTqfgc3elM8TA9hjwIW182vZx SR0VR2PbJipGyGZDyxo0KQFAqAJtwNAJfOVb6yCvpeRALRnZhd+ujYyCoAHPDikwHliu L5cw== Sender: bitcoindev@googlegroups.com X-Forwarded-Encrypted: i=2; AFNElJ8z0vWwExkmvmbPizEYGEpUsF+wteV2mi+khq7mcQHa1KC72MM+1rszi9kvy+zP9Zqqy+qUTjqSsIly@gnusha.org X-Gm-Message-State: AOJu0YxkjpBQgpDqyUUdcKhN6wC7LQToI25r3xmD2jL7OgWn1m1z9EDu T8stdLuULYQrpHvwGpwzFXmJeJ1y/8V27pvohnWdLJ4FeIpTsGbOE646 X-Received: by 2002:a05:6808:1455:b0:467:2be8:6673 with SMTP id 5614622812f47-47899697c70mr11518307b6e.0.1776299306720; Wed, 15 Apr 2026 17:28:26 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AYAyTiJ+RJ6tNb3Qz03wzUXb2Msxm9cxMpCzrtBN0Wx0UpRpwQ==" Received: by 2002:a05:6870:8241:b0:423:2c4e:f14b with SMTP id 586e51a60fabf-4280c5c165bls193404fac.1.-pod-prod-01-us; Wed, 15 Apr 2026 17:28:21 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ+aYwW1zECYnWWS5kc3Y4hIix9UcaCjNb0NcC0+3OVuLDgYlqk1zGJloDQrzGwg2S9IsFqp551sAbcH@googlegroups.com X-Received: by 2002:a05:6808:6a83:b0:467:1376:1cde with SMTP id 5614622812f47-4789d15000fmr12900427b6e.17.1776299301003; Wed, 15 Apr 2026 17:28:21 -0700 (PDT) Received: by 2002:a05:690c:3612:b0:7b3:13f7:5f3a with SMTP id 00721157ae682-7b8ade91770ms7b3; Wed, 15 Apr 2026 17:21:07 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ+UmXhpmlCfgyBUppcpOnxoonX1DwQoiMvuk1LOC+M7a1kEDTsGrwA6i3M6H2D0QAHbXeVxn50Q7w+O@googlegroups.com X-Received: by 2002:a05:690c:6e83:b0:7b2:a7a:62e7 with SMTP id 00721157ae682-7b20a7a7dd9mr181448527b3.24.1776298867272; Wed, 15 Apr 2026 17:21:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776298867; cv=none; d=google.com; s=arc-20240605; b=eaOd70aIM+mQ8897/VcWuVyR/J6bqb/+I51+sC8/VfiUlMK27bKMJD7c6yXvTtdjPQ d/aY5sQr6uaQRkrckgtVkkMHbmttx88WlwB04/i/9dl/XJHgIg3Uz41zCLg8eRDikXNB NS8vDP5/DXGS9VqnVOfi7pzm8Jl7AZI5+34Vl66VDSYhQYYG2x533Us7eMJkBa2kvvQ6 7bL/OOtQVJjnpUYzG0z/1xzT/Kzx4dlzn7W0RdkdS3M2d9wlgmoF7h/Hjf+n+6JEF3uu INTSmeThm904QcNqLNGRTE2YiXZQx1egn+We7RO051PUcHRVzWYgp1Q21OowoxHtlwj/ nSYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=thread-index:content-language:content-transfer-encoding :mime-version:message-id:date:subject:in-reply-to:references:to:from :dkim-signature; bh=9POxfiIny9Mn43TG701pBOjc2ZARSTJKjOgyoXPwD5U=; fh=8uEgj6Zo9nDXu0dDSfRJT0qCKyKOvQqFffEkUGQruSQ=; b=OqISjQVrjUZt2Ih3o+ihukGN8FbG2SHCqYBUsCKZikgLu6hQAsCY0S01VnMvF7ddV9 bdhSqhFg4AHSMoGCa7E7q+VJw9+3MW+yExos/vJ+ezAnk6ley4Q7l9baTZWowx4YeX49 dNWM+nSoxLm1wq/Wi5cIkeMDkRrRJovPIohVNzaopVgoE1ZA7JgVx2MKbcNbqwIskQKO DaAxi/jEjFcnjdBD7pnrZ0abZcX+SyEVrFF34TVeirht1TEk1WlHt6vPdN1FZ4cl5TFT Y5GQHxcL+8HMIjkyfAPb29ek54XkJ8fGJS1WDpxt/Il87wR73jO5qadlONAdLZwreIUE UCxw==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@voskuil.org header.s=google header.b=MaqOFiZ8; spf=pass (google.com: domain of eric@voskuil.org designates 2607:f8b0:4864:20::82b as permitted sender) smtp.mailfrom=eric@voskuil.org; dara=pass header.i=@googlegroups.com Received: from mail-qt1-x82b.google.com (mail-qt1-x82b.google.com. [2607:f8b0:4864:20::82b]) by gmr-mx.google.com with ESMTPS id 00721157ae682-7b769e05d21si1126227b3.6.2026.04.15.17.21.07 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 15 Apr 2026 17:21:07 -0700 (PDT) Received-SPF: pass (google.com: domain of eric@voskuil.org designates 2607:f8b0:4864:20::82b as permitted sender) client-ip=2607:f8b0:4864:20::82b; Received: by mail-qt1-x82b.google.com with SMTP id d75a77b69052e-50da9a7928cso60857251cf.3 for ; Wed, 15 Apr 2026 17:21:07 -0700 (PDT) X-Forwarded-Encrypted: i=1; AFNElJ+zyIpg02fvL9oLdL/19habcxw6s9//CFcHkNp7jKFJ7d2k9c9H4VNPdWldbDNemAM3GLXUJyp/9qM6@googlegroups.com X-Gm-Gg: AeBDiesAQi3mxfoBmdN4qp8YFRPYqz1w/d8jpTj/jM2hpk8TLTBilH9B3qgzLVxw2zM LWlIocj9BSSk+PRftfZyLxbampa5rFpRJtGown78+XonKFKrPouAL9xC/GmtdjWbzS/+15H83kD ScsX7h/UdF4L4b3rFWIfipMlgJzV1v/BeUhGBMsh8gowVnQdwJNE9IfYEBGqaUihqmK3E579p3q dcs39vg7EhUQjR9ayOXVRqvY1q5rUvzz8103fCQsQTGOT5IIs8Q9Y/D30e0WMOJGEyH0uQblHrX U0OTGBSVR3VrZ1jhxs0rkwm3ERE6ZWuM+AHIttXiQFIiizeDWGbTZyPFhVDbpwtmP//p0ahydLl n7ZaiHi3Hod4TkS6mpgjtw8rNie43146gOe11Qx7SsPLjo7LhRs2SeuWb1peISPF/Lw/5IUwd58 AoVmEF7y8vTZCahinXccLu/yr3hkHMOmCrMmFM2fDd X-Received: by 2002:ac8:5708:0:b0:509:3c33:9d0d with SMTP id d75a77b69052e-50dd5aab638mr344710231cf.9.1776298866062; Wed, 15 Apr 2026 17:21:06 -0700 (PDT) Received: from ERICDESKTOP ([216.212.108.156]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-50e294ee389sm679931cf.25.2026.04.15.17.21.05 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Apr 2026 17:21:05 -0700 (PDT) From: To: "'Toby Sharp'" , "'Bitcoin Development Mailing List'" References: <4cd864f3-96dd-4058-bfcd-b1bbf6cfa269n@googlegroups.com> In-Reply-To: <4cd864f3-96dd-4058-bfcd-b1bbf6cfa269n@googlegroups.com> Subject: RE: [bitcoindev] Hornet Update: A declarative executable specification of Bitcoin consensus rules Date: Wed, 15 Apr 2026 20:21:04 -0400 Message-ID: <006501dccd36$ea035fd0$be0a1f70$@voskuil.org> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Mailer: Microsoft Outlook 16.0 Content-Language: en-us Thread-Index: AQIM7pKi29ODGLwkBcXlBApwgU5Lu7WAgycQ X-Original-Sender: eric@voskuil.org X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@voskuil.org header.s=google header.b=MaqOFiZ8; spf=pass (google.com: domain of eric@voskuil.org designates 2607:f8b0:4864:20::82b as permitted sender) smtp.mailfrom=eric@voskuil.org; dara=pass header.i=@googlegroups.com Precedence: list Mailing-list: list bitcoindev@googlegroups.com; contact bitcoindev+owners@googlegroups.com List-ID: X-Google-Group-Id: 786775582512 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Score: -0.7 (/) Hi Toby, I very much support your effort to produce a formal specification. Libbitco= in requires the isolation of consensus rules into purely functional boolean= methods with names that identify the rule under evaluation. I've pasted th= e list of these header/tx/block functions below. You'll notice that `interp= reter::connect()` is evaluated with `transaction::connect()`. This declarat= ive pattern continues into all of script evaluation, but is too large to in= clude. The declarative opcode evaluation portion can be seen here: https://= github.com/libbitcoin/libbitcoin-system/blob/master/include/bitcoin/system/= impl/machine/interpreter.ipp . There are of course certain design decisions= that affect the specific organization, but the outcome is the same. Each r= ule requires and name and functional, isolated evaluation. We see this as the way forward, and are excited to see you tackling the for= mality aspect. We are looking forward to collaborating with you on it. It i= s essential to the usefulness of the formalization that it be applied to a = node in widespread use. So while we long ago implemented the required conse= nsus isolation, we have spent years on the many other aspects of high-perfo= rmance node design. This gives me hope that we can make meaningful progress= on the formalization as well. As you know there is real interest in the co= mmunity to make this happen. Best, Eric // header // ------------------------------------------------------------------------= ---- code header::check() const { if (is_invalid_proof_of_work()) return error::invalid_proof_of_work; if (is_futuristic_timestamp()) return error::futuristic_timestamp; return error::block_success; } code header::accept(const context& ctx) const { if (ctx.is_insufficient_version(version_)) return error::insufficient_block_version; if (ctx.is_anachronistic_timestamp(timestamp_)) return error::anachronistic_timestamp; if (ctx.is_invalid_work(bits_)) return error::incorrect_proof_of_work; return error::block_success; } // transaction // ------------------------------------------------------------------------= ---- code transaction::check() const { const auto coinbase =3D is_coinbase(); if (is_empty()) return error::empty_transaction; if (coinbase && is_invalid_coinbase_size()) return error::invalid_coinbase_script_size; if (!coinbase && is_null_non_coinbase()) return error::previous_output_null; return error::transaction_success; } code transaction::check(const context& ctx) const { const auto bip113 =3D ctx.is_enabled(bip113_rule); if (is_absolute_locked(ctx.height, ctx.timestamp, ctx.median_time_past, bip113)) return error::absolute_time_locked; return error::transaction_success; } code transaction::accept(const context&) const { if (is_coinbase()) return error::transaction_success; if (is_missing_prevouts()) return error::missing_previous_output; if (is_overspent()) return error::spend_exceeds_value; return error::transaction_success; } code transaction::confirm(const context& ctx) const { const auto bip68 =3D ctx.is_enabled(bip68_rule); if (is_coinbase()) return error::transaction_success; if (bip68 && is_relative_locked(ctx.height, ctx.median_time_past)) return error::relative_time_locked; if (is_immature(ctx.height)) return error::coinbase_maturity; if (is_unconfirmed_spend(ctx.height)) return error::unconfirmed_spend; if (is_confirmed_double_spend(ctx.height)) return error::confirmed_double_spend; return error::transaction_success; } code transaction::connect(const context& ctx) const { if (is_coinbase()) return error::transaction_success; for (auto in =3D inputs_->begin(); in !=3D inputs_->end(); ++in) if (const auto ec =3D interpreter::connect(ctx, *this, in)) return ec; return error::transaction_success; } // block // ------------------------------------------------------------------------= ---- code block::check() const { if (is_oversized()) return error::block_size_limit; if (is_first_non_coinbase()) return error::first_not_coinbase; if (is_extra_coinbases()) return error::extra_coinbases; if (is_forward_reference()) return error::forward_reference; if (is_internal_double_spend()) return error::block_internal_double_spend; if (is_invalid_merkle_root()) return error::invalid_transaction_commitment; return check_transactions(); } code block::check(const context& ctx) const { const auto bip141 =3D ctx.is_enabled(bip141_rule); const auto bip34 =3D ctx.is_enabled(bip34_rule); const auto bip50 =3D ctx.is_enabled(bip50_rule); if (bip141 && is_overweight()) return error::block_weight_limit; if (bip34 && is_invalid_coinbase_script(ctx.height)) return error::coinbase_height_mismatch; if (bip50 && is_hash_limit_exceeded()) return error::temporary_hash_limit; if (bip141 && is_invalid_witness_commitment()) return error::invalid_witness_commitment; return check_transactions(ctx); } code block::accept(const context& ctx) const { const auto bip16 =3D ctx.is_enabled(bip16_rule); const auto bip42 =3D ctx.is_enabled(bip42_rule); const auto bip141 =3D ctx.is_enabled(bip141_rule); if (is_overspent(ctx.height, bip42)) return error::coinbase_value_limit; if (is_signature_operations_limited(bip16, bip141)) return error::block_sigop_limit; return accept_transactions(ctx); } > -----Original Message----- > From: 'Toby Sharp' via Bitcoin Development Mailing List > > Sent: Wednesday, April 15, 2026 6:43 PM > To: Bitcoin Development Mailing List > Subject: [bitcoindev] Hornet Update: A declarative executable specificati= on of > Bitcoin consensus rules >=20 > In September 2025, I published a paper on my work towards a pure, formal > specification of Bitcoin's consensus rules. >=20 > > Hornet Node and the Hornet DSL: A minimal, executable specification of > Bitcoin consensus. T Sharp, September 2025. > https://hornetnode.org/paper.html >=20 > I have now completed the C++ executable declarative specification for non= - > script block validation rules: 34 semantic invariants in total. >=20 > ## Background >=20 > Hornet is a minimal, executable specification of Bitcoin's consensus rule= s, > expressed both in declarative C++ and in a purpose-built domain-specific > functional language. >=20 > It is implemented as a suite of modular, dependency-free, modern C++ > libraries and includes a lightweight node capable of Initial Block Downlo= ad > (IBD). >=20 > Hornet's concurrent, lock-free UTXO(1) engine achieves an 11=C3=97 valida= tion > speedup over Bitcoin Core on full-chain replay (discussed in Bitcoin Opte= ch > Newsletter #391). All consensus logic is encapsulated by the declarative > specification described below. >=20 > ## Update 2026-04-15 >=20 > The question of whether a block is valid or invalid can -- and should -- = be > expressed as a Boolean, pure function without state changes or side effec= ts. >=20 > Hornet aims to specify this logic declaratively and semantically, both in= C++ > and in a functional domain-specific language. >=20 > I have now completed the set of non-script block validation rules, organi= zed > with one semantic invariant per rule, with a total of 34 rules composed v= ia a > simple algebra. The first 15 rules are shown below. >=20 > ```cpp > // BLOCK VALIDITY SPECIFICATION > static constexpr auto kConsensusRules =3D All{ > With{MakeHeaderContext, All{ // ## Header Rules > Rule{ValidatePreviousHash}, // A header MUST reference = the hash of > a valid parent block. > Rule{ValidateProofOfWork}, // A header's hash MUST ach= ieve its > own proof-of-work target. > Rule{ValidateDifficultyAdjustment}, // A header's proof-of-work= target > MUST satisfy the difficulty adjustment formula for the timechain. > Rule{ValidateMedianTimePast}, // A header timestamp MUST = be > strictly greater than the median of its 11 ancestors' timestamps. > Rule{ValidateTimestampCurrent}, // A header timestamp MUST = be less > than or equal to network-adjusted time plus 2 hours. > Rule{ValidateVersion} // A header's version numbe= r MUST NOT > have been retired by any activated soft fork. > }}, > With{MakeEnvironmentContext, All{ All{ // ## Local Rules > Rule{ValidateNonEmpty}, // A block MUST contain at = least one > transaction. > Rule{ValidateMerkleRoot}, // A block=E2=80=99s Merkle= root field MUST equal > the unique Merkle root of its transactions. > Rule{ValidateOriginalSizeLimit}, // A block=E2=80=99s serial= ized size excluding > witness flags and data MUST NOT exceed 1,000,000 bytes. > Rule{ValidateCoinbase}, // A block's first transact= ion MUST be its > only coinbase transaction. > Rule{ValidateSignatureOps}, // The total legacy signatu= re-operation > count over all input and output scripts MUST NOT exceed 20,000. > Each{TransactionsInBlock{}, All{ > Rule{ValidateInputCount}, // A transaction MUST conta= in at least > one input. > Rule{ValidateOutputCount}, // A transaction MUST conta= in at least > one output. > Rule{ValidateTransactionSize}, // A transaction's serializ= ed size > excluding witness flags and data MUST NOT exceed 1,000,000 bytes. > Rule{ValidateOutputsNonNegative}, // All transaction output a= mounts > MUST be non-negative. > ... > ``` >=20 > The declarative specification separates *what must be true* from *how it = is > computed*. Each `Rule` line names a C++ function that validates the speci= fic > semantic rule in question, and also gives an English description of the r= ule > being enforced. >=20 > The above statically-typed declarative graph is the executable specificat= ion of > the semantic invariants that precisely determine consensus validity of a = block > in the Bitcoin network. Each Rule node names a validation function that > returns a unique error code if and only if that property fails to hold. >=20 > We can parse the same code to automatically generate an English table of = the > semantic rules: >=20 > | ID | Rule | > |-|-| > ||**Header Rules** > H01|A header MUST reference the hash of a valid parent block. > H02|A header's hash MUST achieve its own proof-of-work target. > H03|A header's proof-of-work target MUST satisfy the difficulty adjustmen= t > formula for the timechain. > H04|A header timestamp MUST be strictly greater than the median of its 11 > ancestors' timestamps. > H05|A header timestamp MUST be less than or equal to network-adjusted > time plus 2 hours. > H06|A header's version number MUST NOT have been retired by any > activated soft fork. > ||**Local Rules** > L01|A block MUST contain at least one transaction. > L02|A block=E2=80=99s Merkle root field MUST equal the unique Merkle root= of its > transactions. > L03|A block=E2=80=99s serialized size excluding witness flags and data MU= ST NOT > exceed 1,000,000 bytes. > L04|A block's first transaction MUST be its only coinbase transaction. > L05|The total legacy signature-operation count over all input and output > scripts MUST NOT exceed 20,000. > L06|A transaction MUST contain at least one input. > L07|A transaction MUST contain at least one output. > L08|A transaction's serialized size excluding witness flags and data MUST= NOT > exceed 1,000,000 bytes. > L09|All transaction output amounts MUST be non-negative. > ... >=20 > For the full declarative C++ spec, see > https://github.com/tobysharp/hornet/tree/main/src/hornetlib/consensus/ru > les/spec.h >=20 > For the resulting semantic summary table, see > https://hornetnode.org/spec.html. >=20 > To read more about Hornet and how it relates to other projects, see > https://hornetnode.org/overview.html. >=20 > ## Future work >=20 > The spending rule S06: "A non-coinbase input MUST satisfy the spent outpu= t's > locking script" is correct, but on its own clearly doesn't capture the in= ternal > complexity of script execution. I am working towards a separate layer of > specification for script rules. >=20 > The declarative C++ specification is a step towards a pure, functional do= main- > specific language for a Bitcoin consensus spec. This will be implemented = in a > future iteration, together with an interpreter and/or compiler. Here is a= n > example of the Hornet DSL: >=20 > ``` > // The total number of signature operations in a block MUST NOT exceed th= e > consensus maximum. > Rule SigOpLimit(block =E2=88=88 Block) > Let SigOpCost : (op =E2=88=88 OpCode) -> int32 > |-> =E2=8E=A7 1 if op =E2=88=88 {Op_CheckSig, Op_CheckSigVerif= y }, > =E2=8E=A8 20 if op =E2=88=88 {Op_CheckMultiSig, Op_CheckMultiSig= Verify}, > =E2=8E=A9 0 otherwise > Require =CE=A3 SigOpCost(inst.opcode) > =E2=88=80 inst =E2=88=88 script.instructions > =E2=88=80 script =E2=88=88 tx.inputs.scriptSig =E2=A7=BA tx.o= utputs.scriptPubKey > =E2=88=80 tx =E2=88=88 block.transactions > =E2=89=A4 20,000 > ``` >=20 > ## Conclusion >=20 > I welcome feedback from the developer community. In particular, do you > believe there is value in a formal specification of consensus rules? Are = there > any aspects of Hornet that you like or dislike? Are there any rules that = you > believe are missing, redundant, unclear, or incorrect? I also welcome any= bug > reports. Thank you. >=20 > T# --=20 You received this message because you are subscribed to the Google Groups "= Bitcoin Development Mailing List" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoindev+unsubscribe@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/= 006501dccd36%24ea035fd0%24be0a1f70%24%40voskuil.org.