From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Wed, 15 Apr 2026 15:45:44 -0700 Received: from mail-oa1-f60.google.com ([209.85.160.60]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wD8zP-00038n-32 for bitcoindev@gnusha.org; Wed, 15 Apr 2026 15:45:43 -0700 Received: by mail-oa1-f60.google.com with SMTP id 586e51a60fabf-42342b79ae4sf13494086fac.1 for ; Wed, 15 Apr 2026 15:45:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1776293137; x=1776897937; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:x-original-sender :mime-version:subject:message-id:to:from:date:from:to:cc:subject :date:message-id:reply-to; bh=pePRDxMN7Wx9gmcbBMXpbuBmlhWZZ0LjGou5TzaXotA=; b=Be2A6FiRJbnpWcjU14cMlSqKUOi5e4Is+5xzDerqF5EXjO2KLtLFTA9oyYL8/YoKhq K96uwS8N1HPg0/COjuiDiuDW3WG4NRgXV0dT7bbdgqucMfBrhprDjbdkvReiKY195Spi +On0tcP+vcgFSmdkxwTlpQUcdDGWxGcoqEaQHM0KRvz7xU3uBiJGgxLC1vPOLgoVRmdd CGWRtGv/Zvs3pwFTa9lMf053fbISKieo4Hoq6MYk2L7cTa0KJIEEVtHtkIxKNG6nl4vm U2KAqA/73RnIi1jKtvmsDK/tz6dYWiOgphvikDav/3jLCfZk/WqQcUhG90wQfMODdMEE DD5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776293137; x=1776897937; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:x-original-sender :mime-version:subject:message-id:to:from:date:x-beenthere :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pePRDxMN7Wx9gmcbBMXpbuBmlhWZZ0LjGou5TzaXotA=; b=jCaQHX9/fiWWaXkxQpVwk/UEiinRO4qkle7nzO0M0y6lHarwNpebBNUVpTmvPA4uwx 4KTsh80KFETkN7FIrD9A9fvMPvoUWWK19aSUptsDP/7RHXumb7tGrc/tjv6+PzQX/sVa +Jf4zisFGxxnvaUJumAasIS25MR7xzjArlo5J/w3NO7Csnrpc6IbSNrqyAkGsDopf66y IIuBaqwEObIFYoRW63oupoBbPtlUkPsJHLyd1r436x+oENVAkhwrobiJ12hdtusjIh3R GS7zHMlo4GnXceg7eo7/ty9MrGPM8mPowGluz5RCcLSMqh5oM+a1ip/XYQEcilPBGQva GsTQ== X-Forwarded-Encrypted: i=1; AFNElJ8sO8+V8S0jHG4DqcsfH0nHgi1lNIqfalq/1z8w04ma8M9gGgKSZMEzHNbussOy8U99F7DigZVvvO5h@gnusha.org X-Gm-Message-State: AOJu0YyC4F7Ic+LTr8gPsB9Ql9f+AgHkkf4w2US6C8j0CqEJgzspIM5r 9+d2zwRyIdzbFa2ctntdjZ1Fga78/zUjRo6iUVusKjwM9f0xadrLd4LU X-Received: by 2002:a05:6871:14f:b0:409:5560:72f8 with SMTP id 586e51a60fabf-423e0a83ffbmr11955616fac.0.1776293137072; Wed, 15 Apr 2026 15:45:37 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AYAyTiKFrF3peADD5WDmNdg9nmfSc9mNVKOLb4ugYA3skOVrxA==" Received: by 2002:a05:6870:56a1:b0:41c:638d:4e66 with SMTP id 586e51a60fabf-4280be9c04als121015fac.0.-pod-prod-00-us; Wed, 15 Apr 2026 15:45:32 -0700 (PDT) X-Received: by 2002:a05:6808:3a05:b0:45f:432:4eed with SMTP id 5614622812f47-47984fcda43mr715670b6e.16.1776293132750; Wed, 15 Apr 2026 15:45:32 -0700 (PDT) Received: by 2002:a05:690c:5512:20b0:7b3:443:26a9 with SMTP id 00721157ae682-7b8ae4839cfms7b3; Wed, 15 Apr 2026 15:42:47 -0700 (PDT) X-Received: by 2002:a05:690c:6ac9:b0:7b7:e34:7206 with SMTP id 00721157ae682-7b863a6d0e1mr15312097b3.14.1776292966193; Wed, 15 Apr 2026 15:42:46 -0700 (PDT) Date: Wed, 15 Apr 2026 15:42:45 -0700 (PDT) From: "'Toby Sharp' via Bitcoin Development Mailing List" To: Bitcoin Development Mailing List Message-Id: <4cd864f3-96dd-4058-bfcd-b1bbf6cfa269n@googlegroups.com> Subject: [bitcoindev] Hornet Update: A declarative executable specification of Bitcoin consensus rules MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_68712_1925759732.1776292965681" X-Original-Sender: toby@hornetnode.org X-Original-From: Toby Sharp Reply-To: Toby Sharp 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: -1.0 (-) ------=_Part_68712_1925759732.1776292965681 Content-Type: multipart/alternative; boundary="----=_Part_68713_1744030968.1776292965681" ------=_Part_68713_1744030968.1776292965681 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable In September 2025, I published a paper on my work towards a pure, formal=20 specification of Bitcoin's consensus rules. > Hornet Node and the Hornet DSL: A minimal, executable specification of=20 Bitcoin consensus. T Sharp, September 2025.=20 https://hornetnode.org/paper.html I have now completed the C++ executable declarative specification for=20 non-script block validation rules: 34 semantic invariants in total. ## Background Hornet is a minimal, executable specification of Bitcoin's consensus rules,= =20 expressed both in declarative C++ and in a purpose-built domain-specific=20 functional language.=20 It is implemented as a suite of modular, dependency-free, modern C++=20 libraries and includes a lightweight node capable of Initial Block Download= =20 (IBD). Hornet's concurrent, lock-free UTXO(1) engine achieves an 11=C3=97 validati= on=20 speedup over Bitcoin Core on full-chain replay (discussed in Bitcoin Optech= =20 Newsletter #391). All consensus logic is encapsulated by the declarative=20 specification described below. ## Update 2026-04-15 The question of whether a block is valid or invalid can -- and should -- be= =20 expressed as a Boolean, pure function without state changes or side effects= . Hornet aims to specify this logic declaratively and semantically, both in= =20 C++ and in a functional domain-specific language. I have now completed the set of non-script block validation rules,=20 organized with one semantic invariant per rule, with a total of 34 rules=20 composed via a simple algebra. The first 15 rules are shown below. ```cpp // BLOCK VALIDITY SPECIFICATION static constexpr auto kConsensusRules =3D All{ With{MakeHeaderContext, All{ // ## Header Rules Rule{ValidatePreviousHash}, // A header MUST reference=20 the hash of a valid parent block. Rule{ValidateProofOfWork}, // A header's hash MUST=20 achieve its own proof-of-work target. Rule{ValidateDifficultyAdjustment}, // A header's proof-of-work= =20 target MUST satisfy the difficulty adjustment formula for the timechain. Rule{ValidateMedianTimePast}, // A header timestamp MUST be= =20 strictly greater than the median of its 11 ancestors' timestamps. Rule{ValidateTimestampCurrent}, // A header timestamp MUST be= =20 less than or equal to network-adjusted time plus 2 hours. Rule{ValidateVersion} // A header's version number= =20 MUST NOT have been retired by any activated soft fork. }}, With{MakeEnvironmentContext, All{ All{ // ## Local Rules Rule{ValidateNonEmpty}, // A block MUST contain at=20 least one transaction. Rule{ValidateMerkleRoot}, // A block=E2=80=99s Merkle r= oot=20 field MUST equal the unique Merkle root of its transactions. Rule{ValidateOriginalSizeLimit}, // A block=E2=80=99s serializ= ed size=20 excluding witness flags and data MUST NOT exceed 1,000,000 bytes. Rule{ValidateCoinbase}, // A block's first=20 transaction MUST be its only coinbase transaction. Rule{ValidateSignatureOps}, // The total legacy=20 signature-operation count over all input and output scripts MUST NOT exceed= =20 20,000. Each{TransactionsInBlock{}, All{ Rule{ValidateInputCount}, // A transaction MUST contain= =20 at least one input. Rule{ValidateOutputCount}, // A transaction MUST contain= =20 at least one output. Rule{ValidateTransactionSize}, // A transaction's serialized= =20 size excluding witness flags and data MUST NOT exceed 1,000,000 bytes. Rule{ValidateOutputsNonNegative}, // All transaction output=20 amounts MUST be non-negative. ... ``` The declarative specification separates *what must be true* from *how it is= =20 computed*. Each `Rule` line names a C++ function that validates the=20 specific semantic rule in question, and also gives an English description= =20 of the rule being enforced. The above statically-typed declarative graph is the executable=20 specification of the semantic invariants that precisely determine consensus= =20 validity of a block in the Bitcoin network. Each Rule node names a=20 validation function that returns a unique error code if and only if that=20 property fails to hold. We can parse the same code to automatically generate an English table of=20 the semantic rules: | ID | Rule |=20 |-|-| ||**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 adjustment= =20 formula for the timechain. H04|A header timestamp MUST be strictly greater than the median of its 11= =20 ancestors' timestamps. H05|A header timestamp MUST be less than or equal to network-adjusted time= =20 plus 2 hours. H06|A header's version number MUST NOT have been retired by any activated= =20 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 o= f its=20 transactions. L03|A block=E2=80=99s serialized size excluding witness flags and data MUST= NOT=20 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=20 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= =20 NOT exceed 1,000,000 bytes. L09|All transaction output amounts MUST be non-negative. ... For the full declarative C++ spec, see=20 https://github.com/tobysharp/hornet/tree/main/src/hornetlib/consensus/rules= /spec.h For the resulting semantic summary table, see=20 https://hornetnode.org/spec.html. To read more about Hornet and how it relates to other projects, see=20 https://hornetnode.org/overview.html. ## Future work The spending rule S06: "A non-coinbase input MUST satisfy the spent=20 output's locking script" is correct, but on its own clearly doesn't capture= =20 the internal complexity of script execution. I am working towards a=20 separate layer of specification for script rules. The declarative C++ specification is a step towards a pure, functional=20 domain-specific language for a Bitcoin consensus spec. This will be=20 implemented in a future iteration, together with an interpreter and/or=20 compiler. Here is an example of the Hornet DSL: ``` // The total number of signature operations in a block MUST NOT exceed the= =20 consensus maximum. Rule SigOpLimit(block =E2=88=88 Block) Let SigOpCost : (op =E2=88=88 OpCode) -> int32=20 |-> =E2=8E=A7 1 if op =E2=88=88 {Op_CheckSig, Op_CheckSigVerify = }, =E2=8E=A8 20 if op =E2=88=88 {Op_CheckMultiSig, Op_CheckMultiSigVe= rify}, =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.out= puts.scriptPubKey =E2=88=80 tx =E2=88=88 block.transactions =E2=89=A4 20,000 ``` ## Conclusion I welcome feedback from the developer community. In particular, do you=20 believe there is value in a formal specification of consensus rules? Are=20 there any aspects of Hornet that you like or dislike? Are there any rules= =20 that you believe are missing, redundant, unclear, or incorrect? I also=20 welcome any bug reports. Thank you. 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/= 4cd864f3-96dd-4058-bfcd-b1bbf6cfa269n%40googlegroups.com. ------=_Part_68713_1744030968.1776292965681 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable In September 2025, I published a paper on my work towards a pure, formal sp= ecification of Bitcoin's consensus rules.

> Hornet Node and t= he Hornet DSL: A minimal, executable specification of Bitcoin consensus. T = Sharp, September 2025. https://hornetnode.org/paper.html

I have = now completed the C++ executable declarative specification for non-script b= lock validation rules: 34 semantic invariants in total.

## Backg= round

Hornet is a minimal, executable specification of Bitcoin's= consensus rules, expressed both in declarative C++ and in a purpose-built = domain-specific functional language.

It is implemented as a sui= te of modular, dependency-free, modern C++ libraries and includes a lightwe= ight node capable of Initial Block Download (IBD).

Hornet's conc= urrent, lock-free UTXO(1) engine achieves an 11=C3=97 validation speedup ov= er Bitcoin Core on full-chain replay (discussed in Bitcoin Optech Newslette= r #391). All consensus logic is encapsulated by the declarative specificati= on described below.

## Update 2026-04-15

The question= of whether a block is valid or invalid can -- and should -- be expressed a= s a Boolean, pure function without state changes or side effects.

Hornet aims to specify this logic declaratively and semantically, both in= C++ and in a functional domain-specific language.

I have now co= mpleted the set of non-script block validation rules, organized with one se= mantic invariant per rule, with a total of 34 rules composed via a simple a= lgebra. The first 15 rules are shown below.

```cpp
// BLOCK= VALIDITY SPECIFICATION
static constexpr auto kConsensusRules =3D All{=
=C2=A0 With{MakeHeaderContext, All{ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0// ## Header Rules
=C2=A0 =C2=A0 Rule{Validate= PreviousHash}, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A header= MUST reference the hash of a valid parent block.
=C2=A0 =C2=A0 Rule{V= alidateProofOfWork}, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0// A header's hash MUST achieve its own proof-of-work target.
=C2= =A0 =C2=A0 Rule{ValidateDifficultyAdjustment}, =C2=A0 =C2=A0 =C2=A0 // A he= ader's proof-of-work target MUST satisfy the difficulty adjustment formula = for the timechain.
=C2=A0 =C2=A0 Rule{ValidateMedianTimePast}, =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A header timestamp MUST be strictly g= reater than the median of its 11 ancestors' timestamps.
=C2=A0 =C2=A0 = Rule{ValidateTimestampCurrent}, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A hea= der timestamp MUST be less than or equal to network-adjusted time plus 2 ho= urs.
=C2=A0 =C2=A0 Rule{ValidateVersion} =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A header's version number MUST= NOT have been retired by any activated soft fork.
=C2=A0 }},
=C2= =A0 With{MakeEnvironmentContext, All{ All{ =C2=A0 =C2=A0 =C2=A0// ## Local = Rules
=C2=A0 =C2=A0 Rule{ValidateNonEmpty}, =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A block MUST contain at least one= transaction.
=C2=A0 =C2=A0 Rule{ValidateMerkleRoot}, =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A block=E2=80=99s Merkle root = field MUST equal the unique Merkle root of its transactions.
=C2=A0 = =C2=A0 Rule{ValidateOriginalSizeLimit}, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/= / A block=E2=80=99s serialized size excluding witness flags and data MUST N= OT exceed 1,000,000 bytes.
=C2=A0 =C2=A0 Rule{ValidateCoinbase}, =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A block's fi= rst transaction MUST be its only coinbase transaction.
=C2=A0 =C2=A0 R= ule{ValidateSignatureOps}, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= // The total legacy signature-operation count over all input and output sc= ripts MUST NOT exceed 20,000.
=C2=A0 =C2=A0 Each{TransactionsInBlock{}= , All{
=C2=A0 =C2=A0 =C2=A0 Rule{ValidateInputCount}, =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // A transaction MUST contain at least o= ne input.
=C2=A0 =C2=A0 =C2=A0 Rule{ValidateOutputCount}, =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// A transaction MUST contain at leas= t one output.
=C2=A0 =C2=A0 =C2=A0 Rule{ValidateTransactionSize}, =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// A transaction's serialized size excluding= witness flags and data MUST NOT exceed 1,000,000 bytes.
=C2=A0 =C2=A0= =C2=A0 Rule{ValidateOutputsNonNegative}, =C2=A0 =C2=A0 =C2=A0 // All trans= action output amounts MUST be non-negative.
=C2=A0 =C2=A0 =C2=A0 ...```

The declarative specification separates *what must be tr= ue* from *how it is computed*. Each `Rule` line names a C++ function that v= alidates the specific semantic rule in question, and also gives an English = description of the rule being enforced.

The above statically-typ= ed declarative graph is the executable specification of the semantic invari= ants that precisely determine consensus validity of a block in the Bitcoin = network. Each Rule node names a validation function that returns a unique e= rror code if and only if that property fails to hold.

We can par= se the same code to automatically generate an English table of the semantic= rules:

| ID | Rule |
|-|-|
||**Header Rules**
H= 01|A header MUST reference the hash of a valid parent block.
H02|A hea= der's hash MUST achieve its own proof-of-work target.
H03|A header's p= roof-of-work target MUST satisfy the difficulty adjustment formula for the = timechain.
H04|A header timestamp MUST be strictly greater than the me= dian of its 11 ancestors' timestamps.
H05|A header timestamp MUST be l= ess 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 exclud= ing witness flags and data MUST NOT exceed 1,000,000 bytes.
L04|A bloc= k's first transaction MUST be its only coinbase transaction.
L05|The t= otal legacy signature-operation count over all input and output scripts MUS= T NOT exceed 20,000.
L06|A transaction MUST contain at least one input= .
L07|A transaction MUST contain at least one output.
L08|A trans= action's serialized size excluding witness flags and data MUST NOT exceed 1= ,000,000 bytes.
L09|All transaction output amounts MUST be non-negativ= e.
...

For the full declarative C++ spec, see https://githu= b.com/tobysharp/hornet/tree/main/src/hornetlib/consensus/rules/spec.h
=
For the resulting semantic summary table, see https://hornetnode.org/= spec.html.

To read more about Hornet and how it relates to other= projects, see https://hornetnode.org/overview.html.

## Future w= ork

The spending rule S06: "A non-coinbase input MUST satisfy th= e spent output's locking script" is correct, but on its own clearly doesn't= capture the internal complexity of script execution. I am working towards = a separate layer of specification for script rules.

The declarat= ive C++ specification is a step towards a pure, functional domain-specific = language for a Bitcoin consensus spec. This will be implemented in a future= iteration, together with an interpreter and/or compiler. Here is an exampl= e of the Hornet DSL:

```
// The total number of signature o= perations in a block MUST NOT exceed the consensus maximum.
Rule SigOp= Limit(block =E2=88=88 Block)
=C2=A0 =C2=A0 Let SigOpCost : (op =E2=88= =88 OpCode) -> int32
=C2=A0 =C2=A0 |-> =E2=8E=A7 =C2=A01 =C2=A0= if op =E2=88=88 {Op_CheckSig, =C2=A0 =C2=A0 =C2=A0Op_CheckSigVerify =C2=A0 = =C2=A0 },
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =E2=8E=A8 20 =C2=A0if op =E2=88= =88 {Op_CheckMultiSig, Op_CheckMultiSigVerify},
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =E2=8E=A9 =C2=A00 =C2=A0otherwise
=C2=A0 =C2=A0 Require =CE=A3 = SigOpCost(inst.opcode)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =E2= =88=80 inst =E2=88=88 script.instructions
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =E2=88=80 script =E2=88=88 tx.inputs.scriptSig =E2=A7=BA tx.o= utputs.scriptPubKey
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =E2=88= =80 tx =E2=88=88 block.transactions
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =E2=89= =A4 20,000
```

## Conclusion

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 Horn= et that you like or dislike? Are there any rules that you believe are missi= ng, redundant, unclear, or incorrect? I also welcome any bug reports. Thank= you.

T#

--
You received this message because you are subscribed to the Google Groups &= quot;Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoind= ev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoind= ev/4cd864f3-96dd-4058-bfcd-b1bbf6cfa269n%40googlegroups.com.
------=_Part_68713_1744030968.1776292965681-- ------=_Part_68712_1925759732.1776292965681--