diff --git a/Cargo.lock b/Cargo.lock index d3cb8de..9d7988a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -510,7 +510,7 @@ dependencies = [ [[package]] name = "simplicity-lang" version = "0.2.0" -source = "git+https://github.com/BlockstreamResearch/rust-simplicity?rev=497b88fec845b3080b61b3939074b59fe24d6dec#497b88fec845b3080b61b3939074b59fe24d6dec" +source = "git+https://github.com/BlockstreamResearch/rust-simplicity?rev=f6e7ecfc43852064780bba6f019b6532d572f166#f6e7ecfc43852064780bba6f019b6532d572f166" dependencies = [ "bitcoin", "bitcoin_hashes", @@ -526,7 +526,7 @@ dependencies = [ [[package]] name = "simplicity-sys" version = "0.2.0" -source = "git+https://github.com/BlockstreamResearch/rust-simplicity?rev=497b88fec845b3080b61b3939074b59fe24d6dec#497b88fec845b3080b61b3939074b59fe24d6dec" +source = "git+https://github.com/BlockstreamResearch/rust-simplicity?rev=f6e7ecfc43852064780bba6f019b6532d572f166#f6e7ecfc43852064780bba6f019b6532d572f166" dependencies = [ "bitcoin_hashes", "cc", diff --git a/Cargo.toml b/Cargo.toml index 3ff2ea2..879640e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ pest = "2.1.3" pest_derive = "2.7.1" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.105" -simplicity-lang = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "497b88fec845b3080b61b3939074b59fe24d6dec" } +simplicity-lang = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "f6e7ecfc43852064780bba6f019b6532d572f166" } miniscript = "11.0.0" either = "1.12.0" itertools = "0.13.0" diff --git a/codegen/src/jet.rs b/codegen/src/jet.rs index 5807007..79c0fd5 100644 --- a/codegen/src/jet.rs +++ b/codegen/src/jet.rs @@ -234,6 +234,16 @@ The assertion fails."#, | Elements::DivMod16 | Elements::DivMod32 | Elements::DivMod64 => "Divide the first integer by the second integer, and return the remainder.", + Elements::DivMod128_64 => r#"Divide the 128-bit integer `a` by the 64-bit integer `b`. +Return a tuple of the quotient `q` and the remainer `r`. + +Use this jet to recursively define wide integer divisions. + +## Preconditions +1. `q` < 2^64 +2. 2^63 ≤ `b` + +Return `(u64::MAX, u64::MAX)` when the preconditions are not satisfied."#, Elements::Divide8 | Elements::Divide16 | Elements::Divide32 @@ -381,6 +391,14 @@ The assertion fails."#, Elements::ScalarNormalize => "Return the canonical representation of the scalar.", Elements::ScalarSquare => "Square a scalar.", Elements::Scale => "Multiply a point by a scalar.", + Elements::HashToCurve => r#" A cryptographic hash function that results in a point on the secp256k1 curve. + +This matches the hash function used to map asset IDs to asset commitments."#, + Elements::Swu => r#"Algebraically distribute a field element over the secp256k1 curve as defined in +["Indifferentiable Hashing to Barreto-Naehrig Curves" by Pierre-Alain Fouque, Mehdi Tibouchi](https://inria.hal.science/hal-01094321/file/FT12.pdf). + +While this by iteslf is not a cryptographic hash function, it can be used as a subrotuine +in a [`hash_to_curve`] function. However the distribution only apporaches uniform when it is called twice."#, // Digital Signatures Elements::Bip0340Verify => r#"Assert that a Schnorr signature matches a public key and message. @@ -401,14 +419,14 @@ This jet should not be used directly."#, - If there is no hash, then the byte `0x00`. - If there is a hash, then the byte `0x01` followed by the given hash (32 bytes)."#, Elements::AssetAmountHash => "Continue a SHA256 hash with the serialization of a confidential asset followed by the serialization of a amount.", - Elements::BuildTapbranch => r#"Return a SHA256 hash of the following: + Elements::BuildTapbranch => r#"Return the SHA256 hash of the following: - The hash of the ASCII string `TapBranch/elements` (32 bytes). - The lexicographically smaller of the two inputs (32 bytes). - The hash of the ASCII string `TapBranch/elements` again (32 bytes). - The lexicographically larger of the two inputs (32 bytes). This builds a taproot from two branches."#, - Elements::BuildTapleafSimplicity => r#"Return a SHA256 hash of the following: + Elements::BuildTapleafSimplicity => r#"Return the SHA256 hash of the following: - The hash of the ASCII string `TapBranch/elements` (32 bytes). - The hash of the ASCII string `TapBranch/elements` again (32 bytes). - The lexicographically smaller of the two inputs (32 bytes). @@ -416,13 +434,13 @@ This builds a taproot from two branches."#, This builds a taproot from two branches."#, Elements::InputAmountsHash => "Return the SHA256 hash of the serialization of each input UTXO's asset and amount fields.", - Elements::InputAnnexesHash => r#"Return a SHA256 hash of the concatenation of the following for every input: + Elements::InputAnnexesHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - If the input has no annex, or isn't a taproot spend, then the byte `0x00`. -- If the input has an annex, then the byte `0x01` followed by a SHA256 hash of the annex (32 bytes)."#, - Elements::InputOutpointsHash => r#"Return a SHA256 hash of the concatenation of the following for every input: +- If the input has an annex, then the byte `0x01` followed by the SHA256 hash of the annex (32 bytes)."#, + Elements::InputOutpointsHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - If the input is not a pegin, then the byte `0x00`. -- The input's serialized previous transaction id (32 bytes). - If the input is a pegin, then the byte `0x01` followed by the parent chain's genesis hash (32 bytes). +- The input's serialized previous transaction id (32 bytes). - The input's previous transaction index in big endian format (4 bytes). IMPORTANT: the index is serialized in big endian format rather than little endian format."#, @@ -431,18 +449,33 @@ IMPORTANT: the index is serialized in big endian format rather than little endia Note that if an input's UTXO uses segwit, then it's scriptSig will necessarily be the empty string. In such cases we still use the SHA256 hash of the empty string."#, Elements::InputScriptsHash => "Return the SHA256 hash of the concatenation of the SHA256 hash of each input UTXO's scriptPubKey.", - Elements::InputSequencesHash => r#"Return a SHA256 hash of the concatenation of the following for every input: -- The inputs sequence number in big endian format (4 bytes). + Elements::InputSequencesHash => r#"Return the SHA256 hash of the concatenation of the following for every input: +- The input's sequence number in big endian format (4 bytes). IMPORTANT, the sequence number is serialized in big endian format rather than little endian format."#, - Elements::InputUtxosHash => r#"Return a SHA256 hash of the following: + Elements::InputUtxoHash => r#"Return the SHA256 hash of the following: +- The serialization of the input UTXO's asset and amount fields. +- The SHA256 hash of the input UTXO's scriptPubKey. + +Return `None` if the input does not exist."#, + Elements::InputUtxosHash => r#"Return the SHA256 hash of the following: - The result of [`input_amounts_hash`] (32 bytes). - The result of [`input_scripts_hash`] (32 bytes)."#, - Elements::InputsHash => r#"Return a SHA256 hash of the following: + Elements::InputHash => r#"Return the SHA256 hash of the following: +- If the input is not a pegin, then the byte `0x00`. +- If the input is a pegin, then the byte `0x01` followed by the parent chain's genesis hash (32 bytes). +- The input's serialized previous transaction id (32 bytes). +- The input's previous transaction index in big endian format (4 bytes). +- The input's sequence number in big endian format (4 bytes). +- If the input has no annex, or isn't a taproot spend, then the byte `0x00`. +- If the input has an annex, then the byte `0x01` followed by the SHA256 hash of the annex (32 bytes). + +Return `None` if the input does not exist."#, + Elements::InputsHash => r#"Return the SHA256 hash of the following: - The result of [`input_outpoints_hash`] (32 bytes). - The result of [`input_sequences_hash`] (32 bytes). - The result of [`input_annexes_hash`] (32 bytes)."#, - Elements::IssuanceAssetAmountsHash => r#"Return a SHA256 hash of the concatenation of the following for every input: + Elements::IssuanceAssetAmountsHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - If the input has no issuance then two bytes `0x00 0x00`. - If the input is has a new issuance then the byte `0x01` followed by a serialization of the calculated issued asset id (32 bytes) followed by the serialization of the (possibly confidential) issued asset amount (9 @@ -455,7 +488,7 @@ IMPORTANT: If there is an issuance but there are no asset issued (i.e. the amoun the vase as the explicit 0 amount, (i.e. `0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00`). Note, the issuance asset id is serialized in the same format as an explicit asset id would be."#, - Elements::IssuanceBlindingEntropyHash => r#"Return a SHA256 hash of the concatenation of the following for every input: + Elements::IssuanceBlindingEntropyHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - If the input has no issuance then the byte `0x00`. - If the input is has a new issuance then the byte `0x01` followed by 32 `0x00` bytes and the new issuance's contract hash field (32 bytes). @@ -464,14 +497,14 @@ nonce field (32 bytes) and the reissuance's entropy field (32 bytes). Note that if the issuance is a new issuance then the blinding nonce field is 32 `0x00` bytes and new issuance's contract hash."#, - Elements::IssuanceRangeProofsHash => r#"Return a SHA256 hash of the concatenation of the following for every input: + Elements::IssuanceRangeProofsHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - The SHA256 hash of the range proof of the input's issuance asset amount (32 bytes). - The SHA256 hash of the range proof of the input's issuance token amount (32 bytes). Note that each the range proof is considered to be the empty string in the case there is no issuance, or if the asset or token amount doesn't exist (i.e is null). The SHA256 hash of the empty string is still used in these cases."#, - Elements::IssuanceTokenAmountsHash => r#"Return a SHA256 hash of the concatenation of the following for every input: + Elements::IssuanceTokenAmountsHash => r#"Return the SHA256 hash of the concatenation of the following for every input: - If the input has no issuance then two bytes `0x00 0x00`. - If the input is has a new issuance then the byte `0x01` followed by a serialization of the calculated issued token id (32 bytes) followed by the serialization of the (possibly confidential) issued token amount (9 @@ -483,13 +516,37 @@ IMPORTANT: If there is an issuance but there are no tokens issued (i.e. the amou the vase as the explicit 0 amount, (i.e. `0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00`). Note, the issuance token id is serialized in the same format as an explicit asset id would be."#, - Elements::IssuancesHash => r#"Return a SHA256 hash of the following: + Elements::IssuanceHash => r#"Return the SHA256 hash of the following: +1. The asset issuance: + - If the input has no issuance then two bytes `0x00 0x00`. + - If the input is has a new issuance then the byte `0x01` followed by a serialization of the calculated issued + asset id (32 bytes) followed by the serialization of the (possibly confidential) issued asset amount (9 bytes or 33 bytes). + - If the input is has a reissuance then the byte `0x01` followed by a serialization of the issued asset id + (32 bytes), followed by the serialization of the (possibly confidential) issued asset amount (9 bytes or 33 bytes). +2. The token issuance: + - If the input has no issuance then two bytes `0x00 0x00`. + - If the input is has a new issuance then the byte `0x01` followed by a serialization of the calculated issued + token id (32 bytes) followed by the serialization of the (possibly confidential) issued token amount (9 bytes or 33 bytes). + - If the input is has a reissuance then the byte `0x01` followed by a serialization of the issued token id (32 bytes), + followed by the serialization of the explicit 0 amount (i.e `0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00`) (9 bytes). +3. The range proofs: + - The SHA256 hash of the range proof of the input's issuance asset amount (32 bytes). + - The SHA256 hash of the range proof of the input's issuance token amount (32 bytes). +4. The blinding entropy: + - If the input has no issuance then the byte `0x00`. + - If the input is has a new issuance then the byte `0x01` followed by 32 `0x00` bytes and the new issuance's + contract hash field (32 bytes). + - If the input is has reissuance then the byte `0x01` followed by a serializaiton of the reissuance's blinding + nonce field (32 bytes) and the reissuance's entropy field (32 bytes). + +Return `None` if the input does not exist."#, + Elements::IssuancesHash => r#"Return the SHA256 hash of the following: - The result of [`issuance_asset_amounts_hash`] (32 bytes). - The result of [`issuance_token_amounts_hash`] (32 bytes). - The result of [`issuance_range_proofs_hash`] (32 bytes). - The result of [`issuance_blinding_entropy_hash`] (32 bytes)."#, - Elements::NonceHash => "Continue a SHA256 hash with the serialization of an optional nonce.", - Elements::OutpointHash => r#"Continue a SHA256 hash with an optional pegin and an outpoint by appending the following: + Elements::NonceHash => "Continue the SHA256 hash with the serialization of an optional nonce.", + Elements::OutpointHash => r#"Continue the SHA256 hash with an optional pegin and an outpoint by appending the following: - If the input is not a pegin, then the byte `0x00`. - If the input is a pegin, then the byte `0x01` followed by the given parent genesis hash (32 bytes). - The input's previous transaction id (32 bytes). @@ -503,14 +560,23 @@ Note that if the output's amount is explicit then the range proof is considered Elements::OutputSurjectionProofsHash => r#"Return the SHA256 hash of the concatenation of the SHA256 hash of each output's surjection proof. Note that if the output's asset is explicit then the surjection proof is considered the empty string."#, - Elements::OutputsHash => r#"Return a SHA256 hash of the following: + Elements::OutputHash => r#"Return the SHA256 hash of the following: +- The serialization of the output's asset and amount fields. +- The serialization of the output's nonce field. +- The SHA256 hash of the output's scriptPubKey. +- The SHA256 hash of the output's range proof. + +Return `None` if the output does not exist. + +Note: the result of [`output_surjection_proofs_hash`] is specifically excluded because surjection proofs are dependent on the inputs as well as the output."#, + Elements::OutputsHash => r#"Return the SHA256 hash of the following: - The result of [`output_amounts_hash`] (32 bytes). - The result of [`output_nonces_hash`] (32 bytes). - The result of [`output_scripts_hash`] (32 bytes). - The result of [`output_range_proofs_hash`] (32 bytes). Note: the result of [`output_surjection_proofs_hash`] is specifically excluded because surjection proofs are dependent on the inputs as well as the output. See also [`tx_hash`]."#, - Elements::SigAllHash => r#"Return a SHA256 hash of the following: + Elements::SigAllHash => r#"Return the SHA256 hash of the following: - The result of [`genesis_block_hash`] (32 bytes). - The result of [`genesis_block_hash`] again (32 bytes). - The result of [`tx_hash`] (32 bytes). @@ -518,11 +584,11 @@ Note: the result of [`output_surjection_proofs_hash`] is specifically excluded b - The result of [`current_index`] (Note: this is in big endian format) (4 bytes). Note: the two copies of the [`genesis_block_hash`] values effectively makes this result a BIP-340 style tagged hash."#, - Elements::TapEnvHash => r#"Return a SHA256 hash of the following: + Elements::TapEnvHash => r#"Return the SHA256 hash of the following: - The result of [`tapleaf_hash`] (32 bytes). - The result of [`tappath_hash`] (32 bytes). - The result of [`internal_key`] (32 bytes)."#, - Elements::TapleafHash => r#"Return a SHA256 hash of the following: + Elements::TapleafHash => r#"Return the SHA256 hash of the following: - The hash of the ASCII string `TapLeaf/elements` (32 bytes). - The hash of the ASCII string `TapLeaf/elements` again (32 bytes). - The result of [`tapleaf_version`] (1 byte). @@ -533,7 +599,7 @@ Note: this matches Element's modified BIP-0341 definition of tapleaf hash."#, Elements::TappathHash => r#"Return a hash of the current input's control block excluding the leaf version and the taproot internal key. Using the notation of BIP-0341, it returns the SHA256 hash of c[33: 33 + 32m]."#, - Elements::TxHash => r#"Return a SHA256 hash of the following: + Elements::TxHash => r#"Return the SHA256 hash of the following: - The result of [`version`] (Note: this is in big endian format) (4 bytes). - The result of [`tx_lock_time`] (Note: this is in big endian format) (4 bytes). - The result of [`inputs_hash`] (32 bytes). @@ -587,6 +653,7 @@ This entropy value is used to compute issued asset and token IDs."#, - Return `Some(Some(x))` if the input has issuance with the reissuance token ID `x`. - Return `Some(None)` if the input has no issuance. - Return `None` if the input does not exist."#, + Elements::LbtcAsset => "Return the asset for Liquid Bitcoin.", // Transaction Elements::CurrentAmount => "Return the [`input_amount`] at the [`current_index`].", Elements::CurrentAnnexHash => "Return the [`input_annex_hash`] at th [`current_index`].", @@ -721,6 +788,7 @@ We assume that Simplicity can be spent in Taproot outputs only, so there always Elements::TotalFee => r#"Return the total amount of fees paid to the given asset id. Return zero for any asset without fees."#, + Elements::TransactionId => "Return the transaction ID.", Elements::Version => "Return the version number of the transaction.", } } @@ -869,16 +937,16 @@ const MULTI_BIT_LOGIC: [Elements; 212] = [ Elements::All8, Elements::All16, Elements::All32, Elements::All64, Elements::And1, Elements::And8, Elements::And16, Elements::And32, Elements::And64, Elements::Ch1, Elements::Ch8, Elements::Ch16, Elements::Ch32, Elements::Ch64, Elements::Complement1, Elements::Complement8, Elements::Complement16, Elements::Complement32, Elements::Complement64, Elements::Eq1, Elements::Eq8, Elements::Eq16, Elements::Eq32, Elements::Eq64, Elements::Eq256, Elements::FullLeftShift16_1, Elements::FullLeftShift16_2, Elements::FullLeftShift16_4, Elements::FullLeftShift16_8, Elements::FullLeftShift32_1, Elements::FullLeftShift32_2, Elements::FullLeftShift32_4, Elements::FullLeftShift32_8, Elements::FullLeftShift32_16, Elements::FullLeftShift64_1, Elements::FullLeftShift64_2, Elements::FullLeftShift64_4, Elements::FullLeftShift64_8, Elements::FullLeftShift64_16, Elements::FullLeftShift64_32, Elements::FullLeftShift8_1, Elements::FullLeftShift8_2, Elements::FullLeftShift8_4, Elements::FullRightShift16_1, Elements::FullRightShift16_2, Elements::FullRightShift16_4, Elements::FullRightShift16_8, Elements::FullRightShift32_1, Elements::FullRightShift32_2, Elements::FullRightShift32_4, Elements::FullRightShift32_8, Elements::FullRightShift32_16, Elements::FullRightShift64_1, Elements::FullRightShift64_2, Elements::FullRightShift64_4, Elements::FullRightShift64_8, Elements::FullRightShift64_16, Elements::FullRightShift64_32, Elements::FullRightShift8_1, Elements::FullRightShift8_2, Elements::FullRightShift8_4, Elements::High1, Elements::High8, Elements::High16, Elements::High32, Elements::High64, Elements::LeftExtend16_32, Elements::LeftExtend16_64, Elements::LeftExtend1_8, Elements::LeftExtend1_16, Elements::LeftExtend1_32, Elements::LeftExtend1_64, Elements::LeftExtend32_64, Elements::LeftExtend8_16, Elements::LeftExtend8_32, Elements::LeftExtend8_64, Elements::LeftPadHigh16_32, Elements::LeftPadHigh16_64, Elements::LeftPadHigh1_8, Elements::LeftPadHigh1_16, Elements::LeftPadHigh1_32, Elements::LeftPadHigh1_64, Elements::LeftPadHigh32_64, Elements::LeftPadHigh8_16, Elements::LeftPadHigh8_32, Elements::LeftPadHigh8_64, Elements::LeftPadLow16_32, Elements::LeftPadLow16_64, Elements::LeftPadLow1_8, Elements::LeftPadLow1_16, Elements::LeftPadLow1_32, Elements::LeftPadLow1_64, Elements::LeftPadLow32_64, Elements::LeftPadLow8_16, Elements::LeftPadLow8_32, Elements::LeftPadLow8_64, Elements::LeftRotate8, Elements::LeftRotate16, Elements::LeftRotate32, Elements::LeftRotate64, Elements::LeftShift8, Elements::LeftShift16, Elements::LeftShift32, Elements::LeftShift64, Elements::LeftShiftWith8, Elements::LeftShiftWith16, Elements::LeftShiftWith32, Elements::LeftShiftWith64, Elements::Leftmost16_1, Elements::Leftmost16_2, Elements::Leftmost16_4, Elements::Leftmost16_8, Elements::Leftmost32_1, Elements::Leftmost32_2, Elements::Leftmost32_4, Elements::Leftmost32_8, Elements::Leftmost32_16, Elements::Leftmost64_1, Elements::Leftmost64_2, Elements::Leftmost64_4, Elements::Leftmost64_8, Elements::Leftmost64_16, Elements::Leftmost64_32, Elements::Leftmost8_1, Elements::Leftmost8_2, Elements::Leftmost8_4, Elements::Low1, Elements::Low8, Elements::Low16, Elements::Low32, Elements::Low64, Elements::Maj1, Elements::Maj8, Elements::Maj16, Elements::Maj32, Elements::Maj64, Elements::Or1, Elements::Or8, Elements::Or16, Elements::Or32, Elements::Or64, Elements::RightExtend16_32, Elements::RightExtend16_64, Elements::RightExtend32_64, Elements::RightExtend8_16, Elements::RightExtend8_32, Elements::RightExtend8_64, Elements::RightPadHigh16_32, Elements::RightPadHigh16_64, Elements::RightPadHigh1_8, Elements::RightPadHigh1_16, Elements::RightPadHigh1_32, Elements::RightPadHigh1_64, Elements::RightPadHigh32_64, Elements::RightPadHigh8_16, Elements::RightPadHigh8_32, Elements::RightPadHigh8_64, Elements::RightPadLow16_32, Elements::RightPadLow16_64, Elements::RightPadLow1_8, Elements::RightPadLow1_16, Elements::RightPadLow1_32, Elements::RightPadLow1_64, Elements::RightPadLow32_64, Elements::RightPadLow8_16, Elements::RightPadLow8_32, Elements::RightPadLow8_64, Elements::RightRotate8, Elements::RightRotate16, Elements::RightRotate32, Elements::RightRotate64, Elements::RightShift8, Elements::RightShift16, Elements::RightShift32, Elements::RightShift64, Elements::RightShiftWith8, Elements::RightShiftWith16, Elements::RightShiftWith32, Elements::RightShiftWith64, Elements::Rightmost16_1, Elements::Rightmost16_2, Elements::Rightmost16_4, Elements::Rightmost16_8, Elements::Rightmost32_1, Elements::Rightmost32_2, Elements::Rightmost32_4, Elements::Rightmost32_8, Elements::Rightmost32_16, Elements::Rightmost64_1, Elements::Rightmost64_2, Elements::Rightmost64_4, Elements::Rightmost64_8, Elements::Rightmost64_16, Elements::Rightmost64_32, Elements::Rightmost8_1, Elements::Rightmost8_2, Elements::Rightmost8_4, Elements::Some1, Elements::Some8, Elements::Some16, Elements::Some32, Elements::Some64, Elements::Xor1, Elements::Xor8, Elements::Xor16, Elements::Xor32, Elements::Xor64, Elements::XorXor1, Elements::XorXor8, Elements::XorXor16, Elements::XorXor32, Elements::XorXor64 ]; #[rustfmt::skip] -const ARITHMETIC: [Elements; 92] = [ - Elements::Add8, Elements::Add16, Elements::Add32, Elements::Add64, Elements::Decrement8, Elements::Decrement16, Elements::Decrement32, Elements::Decrement64, Elements::DivMod8, Elements::DivMod16, Elements::DivMod32, Elements::DivMod64, Elements::Divide8, Elements::Divide16, Elements::Divide32, Elements::Divide64, Elements::Divides8, Elements::Divides16, Elements::Divides32, Elements::Divides64, Elements::FullAdd8, Elements::FullAdd16, Elements::FullAdd32, Elements::FullAdd64, Elements::FullDecrement8, Elements::FullDecrement16, Elements::FullDecrement32, Elements::FullDecrement64, Elements::FullIncrement8, Elements::FullIncrement16, Elements::FullIncrement32, Elements::FullIncrement64, Elements::FullMultiply8, Elements::FullMultiply16, Elements::FullMultiply32, Elements::FullMultiply64, Elements::FullSubtract8, Elements::FullSubtract16, Elements::FullSubtract32, Elements::FullSubtract64, Elements::Increment8, Elements::Increment16, Elements::Increment32, Elements::Increment64, Elements::IsOne8, Elements::IsOne16, Elements::IsOne32, Elements::IsOne64, Elements::IsZero8, Elements::IsZero16, Elements::IsZero32, Elements::IsZero64, Elements::Le8, Elements::Le16, Elements::Le32, Elements::Le64, Elements::Lt8, Elements::Lt16, Elements::Lt32, Elements::Lt64, Elements::Max8, Elements::Max16, Elements::Max32, Elements::Max64, Elements::Median8, Elements::Median16, Elements::Median32, Elements::Median64, Elements::Min8, Elements::Min16, Elements::Min32, Elements::Min64, Elements::Modulo8, Elements::Modulo16, Elements::Modulo32, Elements::Modulo64, Elements::Multiply8, Elements::Multiply16, Elements::Multiply32, Elements::Multiply64, Elements::Negate8, Elements::Negate16, Elements::Negate32, Elements::Negate64, Elements::One8, Elements::One16, Elements::One32, Elements::One64, Elements::Subtract8, Elements::Subtract16, Elements::Subtract32, Elements::Subtract64 +const ARITHMETIC: [Elements; 93] = [ + Elements::Add8, Elements::Add16, Elements::Add32, Elements::Add64, Elements::Decrement8, Elements::Decrement16, Elements::Decrement32, Elements::Decrement64, Elements::DivMod8, Elements::DivMod16, Elements::DivMod32, Elements::DivMod64, Elements::DivMod128_64, Elements::Divide8, Elements::Divide16, Elements::Divide32, Elements::Divide64, Elements::Divides8, Elements::Divides16, Elements::Divides32, Elements::Divides64, Elements::FullAdd8, Elements::FullAdd16, Elements::FullAdd32, Elements::FullAdd64, Elements::FullDecrement8, Elements::FullDecrement16, Elements::FullDecrement32, Elements::FullDecrement64, Elements::FullIncrement8, Elements::FullIncrement16, Elements::FullIncrement32, Elements::FullIncrement64, Elements::FullMultiply8, Elements::FullMultiply16, Elements::FullMultiply32, Elements::FullMultiply64, Elements::FullSubtract8, Elements::FullSubtract16, Elements::FullSubtract32, Elements::FullSubtract64, Elements::Increment8, Elements::Increment16, Elements::Increment32, Elements::Increment64, Elements::IsOne8, Elements::IsOne16, Elements::IsOne32, Elements::IsOne64, Elements::IsZero8, Elements::IsZero16, Elements::IsZero32, Elements::IsZero64, Elements::Le8, Elements::Le16, Elements::Le32, Elements::Le64, Elements::Lt8, Elements::Lt16, Elements::Lt32, Elements::Lt64, Elements::Max8, Elements::Max16, Elements::Max32, Elements::Max64, Elements::Median8, Elements::Median16, Elements::Median32, Elements::Median64, Elements::Min8, Elements::Min16, Elements::Min32, Elements::Min64, Elements::Modulo8, Elements::Modulo16, Elements::Modulo32, Elements::Modulo64, Elements::Multiply8, Elements::Multiply16, Elements::Multiply32, Elements::Multiply64, Elements::Negate8, Elements::Negate16, Elements::Negate32, Elements::Negate64, Elements::One8, Elements::One16, Elements::One32, Elements::One64, Elements::Subtract8, Elements::Subtract16, Elements::Subtract32, Elements::Subtract64 ]; #[rustfmt::skip] const HASH_FUNCTIONS: [Elements; 15] = [ Elements::Sha256Block, Elements::Sha256Ctx8Add1, Elements::Sha256Ctx8Add2, Elements::Sha256Ctx8Add4, Elements::Sha256Ctx8Add8, Elements::Sha256Ctx8Add16, Elements::Sha256Ctx8Add32, Elements::Sha256Ctx8Add64, Elements::Sha256Ctx8Add128, Elements::Sha256Ctx8Add256, Elements::Sha256Ctx8Add512, Elements::Sha256Ctx8AddBuffer511, Elements::Sha256Ctx8Finalize, Elements::Sha256Ctx8Init, Elements::Sha256Iv ]; #[rustfmt::skip] -const ELLIPTIC_CURVE_FUNCTIONS: [Elements; 40] = [ - Elements::Decompress, Elements::FeAdd, Elements::FeInvert, Elements::FeIsOdd, Elements::FeIsZero, Elements::FeMultiply, Elements::FeMultiplyBeta, Elements::FeNegate, Elements::FeNormalize, Elements::FeSquare, Elements::FeSquareRoot, Elements::GeIsOnCurve, Elements::GeNegate, Elements::GejAdd, Elements::GejDouble, Elements::GejEquiv, Elements::GejGeAdd, Elements::GejGeAddEx, Elements::GejGeEquiv, Elements::GejInfinity, Elements::GejIsInfinity, Elements::GejIsOnCurve, Elements::GejNegate, Elements::GejNormalize, Elements::GejRescale, Elements::GejXEquiv, Elements::GejYIsOdd, Elements::Generate, Elements::LinearCombination1, Elements::LinearVerify1, Elements::PointVerify1, Elements::ScalarAdd, Elements::ScalarInvert, Elements::ScalarIsZero, Elements::ScalarMultiply, Elements::ScalarMultiplyLambda, Elements::ScalarNegate, Elements::ScalarNormalize, Elements::ScalarSquare, Elements::Scale +const ELLIPTIC_CURVE_FUNCTIONS: [Elements; 42] = [ + Elements::Decompress, Elements::FeAdd, Elements::FeInvert, Elements::FeIsOdd, Elements::FeIsZero, Elements::FeMultiply, Elements::FeMultiplyBeta, Elements::FeNegate, Elements::FeNormalize, Elements::FeSquare, Elements::FeSquareRoot, Elements::GeIsOnCurve, Elements::GeNegate, Elements::GejAdd, Elements::GejDouble, Elements::GejEquiv, Elements::GejGeAdd, Elements::GejGeAddEx, Elements::GejGeEquiv, Elements::GejInfinity, Elements::GejIsInfinity, Elements::GejIsOnCurve, Elements::GejNegate, Elements::GejNormalize, Elements::GejRescale, Elements::GejXEquiv, Elements::GejYIsOdd, Elements::Generate, Elements::HashToCurve, Elements::LinearCombination1, Elements::LinearVerify1, Elements::PointVerify1, Elements::ScalarAdd, Elements::ScalarInvert, Elements::ScalarIsZero, Elements::ScalarMultiply, Elements::ScalarMultiplyLambda, Elements::ScalarNegate, Elements::ScalarNormalize, Elements::ScalarSquare, Elements::Scale, Elements::Swu ]; #[rustfmt::skip] const DIGITAL_SIGNATURES: [Elements; 1] = [ @@ -890,30 +958,26 @@ const BITCOIN: [Elements; 2] = [ ]; // Elements #[rustfmt::skip] -const SIGNATURE_HASH_MODES: [Elements; 30] = [ - Elements::AnnexHash, Elements::AssetAmountHash, Elements::BuildTapbranch, Elements::BuildTapleafSimplicity, Elements::InputAmountsHash, Elements::InputAnnexesHash, Elements::InputOutpointsHash, Elements::InputScriptSigsHash, Elements::InputScriptsHash, Elements::InputSequencesHash, Elements::InputUtxosHash, Elements::InputsHash, Elements::IssuanceAssetAmountsHash, Elements::IssuanceBlindingEntropyHash, Elements::IssuanceRangeProofsHash, Elements::IssuanceTokenAmountsHash, Elements::IssuancesHash, Elements::NonceHash, Elements::OutpointHash, Elements::OutputAmountsHash, Elements::OutputNoncesHash, Elements::OutputRangeProofsHash, Elements::OutputScriptsHash, Elements::OutputSurjectionProofsHash, Elements::OutputsHash, Elements::SigAllHash, Elements::TapEnvHash, Elements::TapleafHash, Elements::TappathHash, Elements::TxHash +const SIGNATURE_HASH_MODES: [Elements; 34] = [ + Elements::AnnexHash, Elements::AssetAmountHash, Elements::BuildTapbranch, Elements::BuildTapleafSimplicity, Elements::InputAmountsHash, Elements::InputAnnexesHash, Elements::InputHash, Elements::InputOutpointsHash, Elements::InputScriptSigsHash, Elements::InputScriptsHash, Elements::InputSequencesHash, Elements::InputUtxoHash, Elements::InputUtxosHash, Elements::InputsHash, Elements::IssuanceAssetAmountsHash, Elements::IssuanceBlindingEntropyHash, Elements::IssuanceHash, Elements::IssuanceRangeProofsHash, Elements::IssuanceTokenAmountsHash, Elements::IssuancesHash, Elements::NonceHash, Elements::OutpointHash, Elements::OutputAmountsHash, Elements::OutputHash, Elements::OutputNoncesHash, Elements::OutputRangeProofsHash, Elements::OutputScriptsHash, Elements::OutputSurjectionProofsHash, Elements::OutputsHash, Elements::SigAllHash, Elements::TapEnvHash, Elements::TapleafHash, Elements::TappathHash, Elements::TxHash ]; #[rustfmt::skip] const TIME_LOCKS: [Elements; 9] = [ Elements::CheckLockDistance, Elements::CheckLockDuration, Elements::CheckLockHeight, Elements::CheckLockTime, Elements::TxIsFinal, Elements::TxLockDistance, Elements::TxLockDuration, Elements::TxLockHeight, Elements::TxLockTime ]; #[rustfmt::skip] -const ISSUANCE: [Elements; 8] = [ - Elements::CalculateAsset, Elements::CalculateConfidentialToken, Elements::CalculateExplicitToken, Elements::CalculateIssuanceEntropy, Elements::Issuance, Elements::IssuanceAsset, Elements::IssuanceEntropy, Elements::IssuanceToken +const ISSUANCE: [Elements; 9] = [ + Elements::CalculateAsset, Elements::CalculateConfidentialToken, Elements::CalculateExplicitToken, Elements::CalculateIssuanceEntropy, Elements::Issuance, Elements::IssuanceAsset, Elements::IssuanceEntropy, Elements::IssuanceToken, Elements::LbtcAsset ]; #[rustfmt::skip] -const TRANSACTION: [Elements; 49] = [ - Elements::CurrentAmount, Elements::CurrentAnnexHash, Elements::CurrentAsset, Elements::CurrentIndex, Elements::CurrentIssuanceAssetAmount, Elements::CurrentIssuanceAssetProof, Elements::CurrentIssuanceTokenAmount, Elements::CurrentIssuanceTokenProof, Elements::CurrentNewIssuanceContract, Elements::CurrentPegin, Elements::CurrentPrevOutpoint, Elements::CurrentReissuanceBlinding, Elements::CurrentReissuanceEntropy, Elements::CurrentScriptHash, Elements::CurrentScriptSigHash, Elements::CurrentSequence, Elements::GenesisBlockHash, Elements::InputAmount, Elements::InputAnnexHash, Elements::InputAsset, Elements::InputPegin, Elements::InputPrevOutpoint, Elements::InputScriptHash, Elements::InputScriptSigHash, Elements::InputSequence, Elements::InternalKey, Elements::IssuanceAssetAmount, Elements::IssuanceAssetProof, Elements::IssuanceTokenAmount, Elements::IssuanceTokenProof, Elements::LockTime, Elements::NewIssuanceContract, Elements::NumInputs, Elements::NumOutputs, Elements::OutputAmount, Elements::OutputAsset, Elements::OutputIsFee, Elements::OutputNonce, Elements::OutputNullDatum, Elements::OutputRangeProof, Elements::OutputScriptHash, Elements::OutputSurjectionProof, Elements::ReissuanceBlinding, Elements::ReissuanceEntropy, Elements::ScriptCMR, Elements::TapleafVersion, Elements::Tappath, Elements::TotalFee, Elements::Version +const TRANSACTION: [Elements; 50] = [ + Elements::CurrentAmount, Elements::CurrentAnnexHash, Elements::CurrentAsset, Elements::CurrentIndex, Elements::CurrentIssuanceAssetAmount, Elements::CurrentIssuanceAssetProof, Elements::CurrentIssuanceTokenAmount, Elements::CurrentIssuanceTokenProof, Elements::CurrentNewIssuanceContract, Elements::CurrentPegin, Elements::CurrentPrevOutpoint, Elements::CurrentReissuanceBlinding, Elements::CurrentReissuanceEntropy, Elements::CurrentScriptHash, Elements::CurrentScriptSigHash, Elements::CurrentSequence, Elements::GenesisBlockHash, Elements::InputAmount, Elements::InputAnnexHash, Elements::InputAsset, Elements::InputPegin, Elements::InputPrevOutpoint, Elements::InputScriptHash, Elements::InputScriptSigHash, Elements::InputSequence, Elements::InternalKey, Elements::IssuanceAssetAmount, Elements::IssuanceAssetProof, Elements::IssuanceTokenAmount, Elements::IssuanceTokenProof, Elements::LockTime, Elements::NewIssuanceContract, Elements::NumInputs, Elements::NumOutputs, Elements::OutputAmount, Elements::OutputAsset, Elements::OutputIsFee, Elements::OutputNonce, Elements::OutputNullDatum, Elements::OutputRangeProof, Elements::OutputScriptHash, Elements::OutputSurjectionProof, Elements::ReissuanceBlinding, Elements::ReissuanceEntropy, Elements::ScriptCMR, Elements::TapleafVersion, Elements::Tappath, Elements::TotalFee, Elements::TransactionId, Elements::Version ]; #[cfg(test)] mod tests { use super::*; - #[rustfmt::skip] - const ALL: [Elements; 460] = [ - Elements::Add16, Elements::Add32, Elements::Add64, Elements::Add8, Elements::All16, Elements::All32, Elements::All64, Elements::All8, Elements::And1, Elements::And16, Elements::And32, Elements::And64, Elements::And8, Elements::AnnexHash, Elements::AssetAmountHash, Elements::Bip0340Verify, Elements::BuildTapbranch, Elements::BuildTapleafSimplicity, Elements::CalculateAsset, Elements::CalculateConfidentialToken, Elements::CalculateExplicitToken, Elements::CalculateIssuanceEntropy, Elements::Ch1, Elements::Ch16, Elements::Ch32, Elements::Ch64, Elements::Ch8, Elements::CheckLockDistance, Elements::CheckLockDuration, Elements::CheckLockHeight, Elements::CheckLockTime, Elements::CheckSigVerify, Elements::Complement1, Elements::Complement16, Elements::Complement32, Elements::Complement64, Elements::Complement8, Elements::CurrentAmount, Elements::CurrentAnnexHash, Elements::CurrentAsset, Elements::CurrentIndex, Elements::CurrentIssuanceAssetAmount, Elements::CurrentIssuanceAssetProof, Elements::CurrentIssuanceTokenAmount, Elements::CurrentIssuanceTokenProof, Elements::CurrentNewIssuanceContract, Elements::CurrentPegin, Elements::CurrentPrevOutpoint, Elements::CurrentReissuanceBlinding, Elements::CurrentReissuanceEntropy, Elements::CurrentScriptHash, Elements::CurrentScriptSigHash, Elements::CurrentSequence, Elements::Decompress, Elements::Decrement16, Elements::Decrement32, Elements::Decrement64, Elements::Decrement8, Elements::DivMod16, Elements::DivMod32, Elements::DivMod64, Elements::DivMod8, Elements::Divide16, Elements::Divide32, Elements::Divide64, Elements::Divide8, Elements::Divides16, Elements::Divides32, Elements::Divides64, Elements::Divides8, Elements::Eq1, Elements::Eq16, Elements::Eq256, Elements::Eq32, Elements::Eq64, Elements::Eq8, Elements::FeAdd, Elements::FeInvert, Elements::FeIsOdd, Elements::FeIsZero, Elements::FeMultiply, Elements::FeMultiplyBeta, Elements::FeNegate, Elements::FeNormalize, Elements::FeSquare, Elements::FeSquareRoot, Elements::FullAdd16, Elements::FullAdd32, Elements::FullAdd64, Elements::FullAdd8, Elements::FullDecrement16, Elements::FullDecrement32, Elements::FullDecrement64, Elements::FullDecrement8, Elements::FullIncrement16, Elements::FullIncrement32, Elements::FullIncrement64, Elements::FullIncrement8, Elements::FullLeftShift16_1, Elements::FullLeftShift16_2, Elements::FullLeftShift16_4, Elements::FullLeftShift16_8, Elements::FullLeftShift32_1, Elements::FullLeftShift32_16, Elements::FullLeftShift32_2, Elements::FullLeftShift32_4, Elements::FullLeftShift32_8, Elements::FullLeftShift64_1, Elements::FullLeftShift64_16, Elements::FullLeftShift64_2, Elements::FullLeftShift64_32, Elements::FullLeftShift64_4, Elements::FullLeftShift64_8, Elements::FullLeftShift8_1, Elements::FullLeftShift8_2, Elements::FullLeftShift8_4, Elements::FullMultiply16, Elements::FullMultiply32, Elements::FullMultiply64, Elements::FullMultiply8, Elements::FullRightShift16_1, Elements::FullRightShift16_2, Elements::FullRightShift16_4, Elements::FullRightShift16_8, Elements::FullRightShift32_1, Elements::FullRightShift32_16, Elements::FullRightShift32_2, Elements::FullRightShift32_4, Elements::FullRightShift32_8, Elements::FullRightShift64_1, Elements::FullRightShift64_16, Elements::FullRightShift64_2, Elements::FullRightShift64_32, Elements::FullRightShift64_4, Elements::FullRightShift64_8, Elements::FullRightShift8_1, Elements::FullRightShift8_2, Elements::FullRightShift8_4, Elements::FullSubtract16, Elements::FullSubtract32, Elements::FullSubtract64, Elements::FullSubtract8, Elements::GeIsOnCurve, Elements::GeNegate, Elements::GejAdd, Elements::GejDouble, Elements::GejEquiv, Elements::GejGeAdd, Elements::GejGeAddEx, Elements::GejGeEquiv, Elements::GejInfinity, Elements::GejIsInfinity, Elements::GejIsOnCurve, Elements::GejNegate, Elements::GejNormalize, Elements::GejRescale, Elements::GejXEquiv, Elements::GejYIsOdd, Elements::Generate, Elements::GenesisBlockHash, Elements::High1, Elements::High16, Elements::High32, Elements::High64, Elements::High8, Elements::Increment16, Elements::Increment32, Elements::Increment64, Elements::Increment8, Elements::InputAmount, Elements::InputAmountsHash, Elements::InputAnnexHash, Elements::InputAnnexesHash, Elements::InputAsset, Elements::InputOutpointsHash, Elements::InputPegin, Elements::InputPrevOutpoint, Elements::InputScriptHash, Elements::InputScriptSigHash, Elements::InputScriptSigsHash, Elements::InputScriptsHash, Elements::InputSequence, Elements::InputSequencesHash, Elements::InputUtxosHash, Elements::InputsHash, Elements::InternalKey, Elements::IsOne16, Elements::IsOne32, Elements::IsOne64, Elements::IsOne8, Elements::IsZero16, Elements::IsZero32, Elements::IsZero64, Elements::IsZero8, Elements::Issuance, Elements::IssuanceAsset, Elements::IssuanceAssetAmount, Elements::IssuanceAssetAmountsHash, Elements::IssuanceAssetProof, Elements::IssuanceBlindingEntropyHash, Elements::IssuanceEntropy, Elements::IssuanceRangeProofsHash, Elements::IssuanceToken, Elements::IssuanceTokenAmount, Elements::IssuanceTokenAmountsHash, Elements::IssuanceTokenProof, Elements::IssuancesHash, Elements::Le16, Elements::Le32, Elements::Le64, Elements::Le8, Elements::LeftExtend16_32, Elements::LeftExtend16_64, Elements::LeftExtend1_16, Elements::LeftExtend1_32, Elements::LeftExtend1_64, Elements::LeftExtend1_8, Elements::LeftExtend32_64, Elements::LeftExtend8_16, Elements::LeftExtend8_32, Elements::LeftExtend8_64, Elements::LeftPadHigh16_32, Elements::LeftPadHigh16_64, Elements::LeftPadHigh1_16, Elements::LeftPadHigh1_32, Elements::LeftPadHigh1_64, Elements::LeftPadHigh1_8, Elements::LeftPadHigh32_64, Elements::LeftPadHigh8_16, Elements::LeftPadHigh8_32, Elements::LeftPadHigh8_64, Elements::LeftPadLow16_32, Elements::LeftPadLow16_64, Elements::LeftPadLow1_16, Elements::LeftPadLow1_32, Elements::LeftPadLow1_64, Elements::LeftPadLow1_8, Elements::LeftPadLow32_64, Elements::LeftPadLow8_16, Elements::LeftPadLow8_32, Elements::LeftPadLow8_64, Elements::LeftRotate16, Elements::LeftRotate32, Elements::LeftRotate64, Elements::LeftRotate8, Elements::LeftShift16, Elements::LeftShift32, Elements::LeftShift64, Elements::LeftShift8, Elements::LeftShiftWith16, Elements::LeftShiftWith32, Elements::LeftShiftWith64, Elements::LeftShiftWith8, Elements::Leftmost16_1, Elements::Leftmost16_2, Elements::Leftmost16_4, Elements::Leftmost16_8, Elements::Leftmost32_1, Elements::Leftmost32_16, Elements::Leftmost32_2, Elements::Leftmost32_4, Elements::Leftmost32_8, Elements::Leftmost64_1, Elements::Leftmost64_16, Elements::Leftmost64_2, Elements::Leftmost64_32, Elements::Leftmost64_4, Elements::Leftmost64_8, Elements::Leftmost8_1, Elements::Leftmost8_2, Elements::Leftmost8_4, Elements::LinearCombination1, Elements::LinearVerify1, Elements::LockTime, Elements::Low1, Elements::Low16, Elements::Low32, Elements::Low64, Elements::Low8, Elements::Lt16, Elements::Lt32, Elements::Lt64, Elements::Lt8, Elements::Maj1, Elements::Maj16, Elements::Maj32, Elements::Maj64, Elements::Maj8, Elements::Max16, Elements::Max32, Elements::Max64, Elements::Max8, Elements::Median16, Elements::Median32, Elements::Median64, Elements::Median8, Elements::Min16, Elements::Min32, Elements::Min64, Elements::Min8, Elements::Modulo16, Elements::Modulo32, Elements::Modulo64, Elements::Modulo8, Elements::Multiply16, Elements::Multiply32, Elements::Multiply64, Elements::Multiply8, Elements::Negate16, Elements::Negate32, Elements::Negate64, Elements::Negate8, Elements::NewIssuanceContract, Elements::NonceHash, Elements::NumInputs, Elements::NumOutputs, Elements::One16, Elements::One32, Elements::One64, Elements::One8, Elements::Or1, Elements::Or16, Elements::Or32, Elements::Or64, Elements::Or8, Elements::OutpointHash, Elements::OutputAmount, Elements::OutputAmountsHash, Elements::OutputAsset, Elements::OutputIsFee, Elements::OutputNonce, Elements::OutputNoncesHash, Elements::OutputNullDatum, Elements::OutputRangeProof, Elements::OutputRangeProofsHash, Elements::OutputScriptHash, Elements::OutputScriptsHash, Elements::OutputSurjectionProof, Elements::OutputSurjectionProofsHash, Elements::OutputsHash, Elements::ParseLock, Elements::ParseSequence, Elements::PointVerify1, Elements::ReissuanceBlinding, Elements::ReissuanceEntropy, Elements::RightExtend16_32, Elements::RightExtend16_64, Elements::RightExtend32_64, Elements::RightExtend8_16, Elements::RightExtend8_32, Elements::RightExtend8_64, Elements::RightPadHigh16_32, Elements::RightPadHigh16_64, Elements::RightPadHigh1_16, Elements::RightPadHigh1_32, Elements::RightPadHigh1_64, Elements::RightPadHigh1_8, Elements::RightPadHigh32_64, Elements::RightPadHigh8_16, Elements::RightPadHigh8_32, Elements::RightPadHigh8_64, Elements::RightPadLow16_32, Elements::RightPadLow16_64, Elements::RightPadLow1_16, Elements::RightPadLow1_32, Elements::RightPadLow1_64, Elements::RightPadLow1_8, Elements::RightPadLow32_64, Elements::RightPadLow8_16, Elements::RightPadLow8_32, Elements::RightPadLow8_64, Elements::RightRotate16, Elements::RightRotate32, Elements::RightRotate64, Elements::RightRotate8, Elements::RightShift16, Elements::RightShift32, Elements::RightShift64, Elements::RightShift8, Elements::RightShiftWith16, Elements::RightShiftWith32, Elements::RightShiftWith64, Elements::RightShiftWith8, Elements::Rightmost16_1, Elements::Rightmost16_2, Elements::Rightmost16_4, Elements::Rightmost16_8, Elements::Rightmost32_1, Elements::Rightmost32_16, Elements::Rightmost32_2, Elements::Rightmost32_4, Elements::Rightmost32_8, Elements::Rightmost64_1, Elements::Rightmost64_16, Elements::Rightmost64_2, Elements::Rightmost64_32, Elements::Rightmost64_4, Elements::Rightmost64_8, Elements::Rightmost8_1, Elements::Rightmost8_2, Elements::Rightmost8_4, Elements::ScalarAdd, Elements::ScalarInvert, Elements::ScalarIsZero, Elements::ScalarMultiply, Elements::ScalarMultiplyLambda, Elements::ScalarNegate, Elements::ScalarNormalize, Elements::ScalarSquare, Elements::Scale, Elements::ScriptCMR, Elements::Sha256Block, Elements::Sha256Ctx8Add1, Elements::Sha256Ctx8Add128, Elements::Sha256Ctx8Add16, Elements::Sha256Ctx8Add2, Elements::Sha256Ctx8Add256, Elements::Sha256Ctx8Add32, Elements::Sha256Ctx8Add4, Elements::Sha256Ctx8Add512, Elements::Sha256Ctx8Add64, Elements::Sha256Ctx8Add8, Elements::Sha256Ctx8AddBuffer511, Elements::Sha256Ctx8Finalize, Elements::Sha256Ctx8Init, Elements::Sha256Iv, Elements::SigAllHash, Elements::Some1, Elements::Some16, Elements::Some32, Elements::Some64, Elements::Some8, Elements::Subtract16, Elements::Subtract32, Elements::Subtract64, Elements::Subtract8, Elements::TapEnvHash, Elements::TapleafHash, Elements::TapleafVersion, Elements::Tappath, Elements::TappathHash, Elements::TotalFee, Elements::TxHash, Elements::TxIsFinal, Elements::TxLockDistance, Elements::TxLockDuration, Elements::TxLockHeight, Elements::TxLockTime, Elements::Verify, Elements::Version, Elements::Xor1, Elements::Xor16, Elements::Xor32, Elements::Xor64, Elements::Xor8, Elements::XorXor1, Elements::XorXor16, Elements::XorXor32, Elements::XorXor64, Elements::XorXor8 - ]; #[rustfmt::skip] const DISABLED: [Elements; 2] = [ Elements::CheckSigVerify, Elements::Verify @@ -921,22 +985,19 @@ mod tests { #[test] fn correct_categorization() { - for jet in ALL { + for jet in Elements::ALL { match Category::ALL.iter().find(|c| c.contains(&jet)) { Some(category) => { - match Category::ALL + if let Some(other) = Category::ALL .into_iter() .filter(|other| other != category) .find(|other| other.contains(&jet)) { - Some(other) => panic!( - "{jet} is assigned conflicting categories {category} and {other}" - ), - None => {} + panic!("{jet} is assigned conflicting categories {category} and {other}"); } } None => { - assert!(DISABLED.contains(&jet), "{jet} is not categorized") + assert!(DISABLED.contains(&jet), "{jet} is not categorized"); } } } diff --git a/justfile b/justfile index da6eff9..6041a45 100644 --- a/justfile +++ b/justfile @@ -8,11 +8,11 @@ fmtcheck: # Run code linter lint: - cargo clippy --all-targets -- --deny warnings + cargo clippy --all-targets --workspace -- --deny warnings # Run unit tests test: - cargo test + cargo test --workspace # Check code (CI) check: diff --git a/src/compile.rs b/src/compile.rs index c4329cb..4508e29 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -58,13 +58,25 @@ struct Scope { /// Later assignments occur higher in the tree than earlier assignments. /// ``` variables: Vec>, + ctx: simplicity::types::Context, } impl Scope { - /// Create a new [`Scope`] for an `input` value that matches the pattern. - pub fn new(input: Pattern) -> Self { + /// Create the main scope. + /// + /// _This function should be called at the start of the compilation and then never again._ + pub fn new() -> Self { + Self { + variables: vec![vec![Pattern::Ignore]], + ctx: simplicity::types::Context::new(), + } + } + + /// Create a child scope for a function that takes `input` of the given pattern. + pub fn child(&self, input: Pattern) -> Self { Self { variables: vec![vec![input]], + ctx: self.ctx.shallow_clone(), } } @@ -144,7 +156,12 @@ impl Scope { /// /// The expression `drop (IOH & OH)` returns the seeked value. pub fn get(&self, target: &BasePattern) -> Option> { - BasePattern::from(&self.get_input_pattern()).translate(target) + BasePattern::from(&self.get_input_pattern()).translate(&self.ctx, target) + } + + /// Access the Simplicity type inference context. + pub fn ctx(&self) -> &simplicity::types::Context { + &self.ctx } } @@ -157,37 +174,30 @@ fn compile_blk( if index >= stmts.len() { return match last_expr { Some(expr) => expr.compile(scope), - None => Ok(PairBuilder::unit()), + None => Ok(PairBuilder::unit(scope.ctx())), }; } match &stmts[index] { Statement::Assignment(assignment) => { let expr = assignment.expression().compile(scope)?; scope.insert(assignment.pattern().clone()); - let left = expr.pair(PairBuilder::iden()); + let left = expr.pair(PairBuilder::iden(scope.ctx())); let right = compile_blk(stmts, scope, index + 1, last_expr)?; left.comp(&right).with_span(assignment) } Statement::Expression(expression) => { let left = expression.compile(scope)?; let right = compile_blk(stmts, scope, index + 1, last_expr)?; - combine_seq(left, right).with_span(expression) + let pair = left.pair(right); + let drop_iden = ProgNode::drop_(&ProgNode::iden(scope.ctx())); + pair.comp(&drop_iden).with_span(expression) } } } -fn combine_seq( - a: PairBuilder, - b: PairBuilder, -) -> Result, simplicity::types::Error> { - let pair = a.pair(b); - let drop_iden = ProgNode::drop_(&ProgNode::iden()); - pair.comp(&drop_iden) -} - impl Program { pub fn compile(&self) -> Result { - let mut scope = Scope::new(Pattern::Ignore); + let mut scope = Scope::new(); self.main().compile(&mut scope).map(PairBuilder::build) } } @@ -212,9 +222,9 @@ impl SingleExpression { SingleExpressionInner::Constant(value) => { // FIXME: Handle values that are not powers of two (requires updated rust-simplicity API) let value = StructuralValue::from(value); - PairBuilder::unit_const_value(value.into()) + PairBuilder::unit_const_value(scope.ctx(), value.into()) } - SingleExpressionInner::Witness(name) => PairBuilder::witness(name.clone()), + SingleExpressionInner::Witness(name) => PairBuilder::witness(scope.ctx(), name.clone()), SingleExpressionInner::Variable(identifier) => scope .get(&BasePattern::Identifier(identifier.clone())) .ok_or(Error::UndefinedVariable(identifier.clone())) @@ -227,7 +237,7 @@ impl SingleExpression { .collect::>, RichError>>()?; let tree = BTreeSlice::from_slice(&compiled); tree.fold(PairBuilder::pair) - .unwrap_or_else(PairBuilder::unit) + .unwrap_or_else(|| PairBuilder::unit(scope.ctx())) } SingleExpressionInner::List(elements) => { let compiled = elements @@ -240,14 +250,14 @@ impl SingleExpression { |block| { let tree = BTreeSlice::from_slice(block); match tree.fold(PairBuilder::pair) { - None => PairBuilder::unit().injl(), + None => PairBuilder::unit(scope.ctx()).injl(), Some(pair) => pair.injr(), } }, PairBuilder::pair, ) } - SingleExpressionInner::Option(None) => PairBuilder::unit().injl(), + SingleExpressionInner::Option(None) => PairBuilder::unit(scope.ctx()).injl(), SingleExpressionInner::Either(Either::Left(inner)) => { inner.compile(scope).map(PairBuilder::injl)? } @@ -259,12 +269,13 @@ impl SingleExpression { SingleExpressionInner::Match(match_) => match_.compile(scope)?, }; - expr.as_ref() - .cached_data() - .arrow() - .target - .unify(&StructuralType::from(self.ty()).to_unfinalized(), "") - .map_err(|e| Error::CannotCompile(e.to_string())) + scope + .ctx() + .unify( + &expr.as_ref().cached_data().arrow().target, + &StructuralType::from(self.ty()).to_unfinalized(scope.ctx()), + "", + ) .with_span(self)?; Ok(expr) } @@ -277,33 +288,33 @@ impl Call { match self.name() { CallName::Jet(name) => { - let jet = ProgNode::jet(*name); + let jet = ProgNode::jet(scope.ctx(), *name); args.comp(&jet).with_span(self) } CallName::UnwrapLeft(..) => { - let left_and_unit = args.pair(PairBuilder::unit()); + let left_and_unit = args.pair(PairBuilder::unit(scope.ctx())); let fail_cmr = Cmr::fail(FailEntropy::ZERO); - let get_inner = ProgNode::assertl_take(&ProgNode::iden(), fail_cmr); + let get_inner = ProgNode::assertl_take(&ProgNode::iden(scope.ctx()), fail_cmr); left_and_unit.comp(&get_inner).with_span(self) } CallName::UnwrapRight(..) | CallName::Unwrap => { - let right_and_unit = args.pair(PairBuilder::unit()); + let right_and_unit = args.pair(PairBuilder::unit(scope.ctx())); let fail_cmr = Cmr::fail(FailEntropy::ZERO); - let get_inner = ProgNode::assertr_take(fail_cmr, &ProgNode::iden()); + let get_inner = ProgNode::assertr_take(fail_cmr, &ProgNode::iden(scope.ctx())); right_and_unit.comp(&get_inner).with_span(self) } CallName::IsNone(..) => { - let sum_and_unit = args.pair(PairBuilder::unit()); - let is_right = ProgNode::case_true_false(); + let sum_and_unit = args.pair(PairBuilder::unit(scope.ctx())); + let is_right = ProgNode::case_true_false(scope.ctx()); sum_and_unit.comp(&is_right).with_span(self) } CallName::Assert => { - let jet = ProgNode::jet(Elements::Verify); + let jet = ProgNode::jet(scope.ctx(), Elements::Verify); args.comp(&jet).with_span(self) } CallName::Panic => { // panic! ignores its arguments - Ok(PairBuilder::fail(FailEntropy::ZERO)) + Ok(PairBuilder::fail(scope.ctx(), FailEntropy::ZERO)) } CallName::TypeCast(..) => { // A cast converts between two structurally equal types. @@ -313,18 +324,18 @@ impl Call { Ok(args) } CallName::Custom(function) => { - let mut function_scope = Scope::new(function.params_pattern()); + let mut function_scope = scope.child(function.params_pattern()); let body = function.body().compile(&mut function_scope)?; args.comp(&body).with_span(self) } CallName::Fold(function, bound) => { - let mut function_scope = Scope::new(function.params_pattern()); + let mut function_scope = scope.child(function.params_pattern()); let body = function.body().compile(&mut function_scope)?; let fold_body = list_fold(*bound, body.as_ref()).with_span(self)?; args.comp(&fold_body).with_span(self) } CallName::ForWhile(function, bit_width) => { - let mut function_scope = Scope::new(function.params_pattern()); + let mut function_scope = scope.child(function.params_pattern()); let body = function.body().compile(&mut function_scope)?; let fold_body = for_while(*bit_width, body).with_span(self)?; args.comp(&fold_body).with_span(self) @@ -351,7 +362,8 @@ fn list_fold(bound: NonZeroPow2Usize, f: &ProgNode) -> Result Result Result Result, simplicity::types::Error> { + let ctx = f.inference_context(); let f_output = ProgNode::o() - .h() - .pair(ProgNode::i().h().pair(ProgNode::bit(false))) + .h(ctx) + .pair(ProgNode::i().h(ctx).pair(ProgNode::bit(ctx, false))) .comp(f)?; - let case_input = f_output.pair(ProgNode::i().h()); + let case_input = f_output.pair(ProgNode::i().h(ctx)); - let x = ProgNode::injl(ProgNode::o().h().as_ref()); + let x = ProgNode::injl(ProgNode::o().h(ctx).as_ref()); let f_output = ProgNode::o() - .h() - .pair(ProgNode::i().h().pair(ProgNode::bit(true))) + .h(ctx) + .pair(ProgNode::i().h(ctx).pair(ProgNode::bit(ctx, true))) .comp(f)?; let case_output = ProgNode::case(&x, f_output.as_ref())?; @@ -443,12 +458,13 @@ fn for_while( * f : A × (C × 2^(2^(n + 1))) → B + A */ fn adapt_f(f: &ProgNode) -> Result, simplicity::types::Error> { - let f_input = ProgNode::o().h().pair( + let ctx = f.inference_context(); + let f_input = ProgNode::o().h(ctx).pair( ProgNode::i() .o() .o() - .h() - .pair(ProgNode::i().o().i().h().pair(ProgNode::i().i().h())), + .h(ctx) + .pair(ProgNode::i().o().i().h(ctx).pair(ProgNode::i().i().h(ctx))), ); f_input.comp(f) } @@ -536,7 +552,7 @@ impl Match { scope.pop_scope(); let scrutinee = self.scrutinee().compile(scope)?; - let input = scrutinee.pair(PairBuilder::iden()); + let input = scrutinee.pair(PairBuilder::iden(scope.ctx())); let output = ProgNode::case(left.as_ref(), right.as_ref()).with_span(self)?; input.comp(&output).with_span(self) } diff --git a/src/jet.rs b/src/jet.rs index 1e2140b..f088815 100644 --- a/src/jet.rs +++ b/src/jet.rs @@ -314,6 +314,7 @@ pub fn source_type(jet: Elements) -> Vec { | Elements::Divide64 | Elements::Modulo64 | Elements::Divides64 => vec![U64.into(), U64.into()], + Elements::DivMod128_64 => vec![U128.into(), U64.into()], Elements::FullAdd8 | Elements::FullSubtract8 => vec![bool(), U8.into(), U8.into()], Elements::FullAdd16 | Elements::FullSubtract16 => vec![bool(), U16.into(), U16.into()], Elements::FullAdd32 | Elements::FullSubtract32 => vec![bool(), U32.into(), U32.into()], @@ -389,8 +390,10 @@ pub fn source_type(jet: Elements) -> Vec { | Elements::FeInvert | Elements::FeSquareRoot | Elements::FeIsZero - | Elements::FeIsOdd => vec![Fe.into()], + | Elements::FeIsOdd + | Elements::Swu => vec![Fe.into()], Elements::FeAdd | Elements::FeMultiply => vec![Fe.into(), Fe.into()], + Elements::HashToCurve => vec![U256.into()], /* * Digital signatures */ @@ -490,7 +493,9 @@ pub fn source_type(jet: Elements) -> Vec { | Elements::CurrentIssuanceTokenProof | Elements::TapleafVersion | Elements::Version - | Elements::GenesisBlockHash => vec![], + | Elements::GenesisBlockHash + | Elements::LbtcAsset + | Elements::TransactionId => vec![], Elements::OutputAsset | Elements::OutputAmount | Elements::OutputNonce @@ -498,6 +503,7 @@ pub fn source_type(jet: Elements) -> Vec { | Elements::OutputIsFee | Elements::OutputSurjectionProof | Elements::OutputRangeProof + | Elements::OutputHash | Elements::InputPegin | Elements::InputPrevOutpoint | Elements::InputAsset @@ -506,13 +512,16 @@ pub fn source_type(jet: Elements) -> Vec { | Elements::InputSequence | Elements::InputAnnexHash | Elements::InputScriptSigHash + | Elements::InputHash + | Elements::InputUtxoHash | Elements::ReissuanceBlinding | Elements::NewIssuanceContract | Elements::ReissuanceEntropy | Elements::IssuanceAssetAmount | Elements::IssuanceTokenAmount | Elements::IssuanceAssetProof - | Elements::IssuanceTokenProof => vec![U32.into()], + | Elements::IssuanceTokenProof + | Elements::IssuanceHash => vec![U32.into()], Elements::OutputNullDatum => vec![U32.into(), U32.into()], Elements::TotalFee => vec![ExplicitAsset.into()], Elements::Tappath => vec![U8.into()], @@ -835,6 +844,7 @@ pub fn target_type(jet: Elements) -> AliasedType { Elements::DivMod16 => tuple([U16, U16]), Elements::DivMod32 => tuple([U32, U32]), Elements::DivMod64 => tuple([U64, U64]), + Elements::DivMod128_64 => tuple([U64, U64]), /* * Hash functions */ @@ -865,7 +875,7 @@ pub fn target_type(jet: Elements) -> AliasedType { | Elements::ScalarIsZero | Elements::FeIsZero | Elements::FeIsOdd => bool(), - Elements::GeNegate => Ge.into(), + Elements::GeNegate | Elements::HashToCurve | Elements::Swu => Ge.into(), Elements::Decompress | Elements::GejNormalize => option(Ge), Elements::LinearCombination1 | Elements::Scale @@ -974,7 +984,9 @@ pub fn target_type(jet: Elements) -> AliasedType { | Elements::CurrentScriptSigHash | Elements::CurrentIssuanceAssetProof | Elements::CurrentIssuanceTokenProof - | Elements::GenesisBlockHash => U256.into(), + | Elements::GenesisBlockHash + | Elements::LbtcAsset + | Elements::TransactionId => U256.into(), Elements::InternalKey => Pubkey.into(), Elements::LockTime => Lock.into(), Elements::InputSequence => option(U32), @@ -984,14 +996,18 @@ pub fn target_type(jet: Elements) -> AliasedType { Elements::OutputScriptHash | Elements::OutputSurjectionProof | Elements::OutputRangeProof + | Elements::OutputHash | Elements::CurrentPegin | Elements::CurrentAnnexHash | Elements::CurrentNewIssuanceContract | Elements::CurrentReissuanceEntropy | Elements::InputScriptHash | Elements::InputScriptSigHash + | Elements::InputHash + | Elements::InputUtxoHash | Elements::IssuanceAssetProof | Elements::IssuanceTokenProof + | Elements::IssuanceHash | Elements::Tappath => option(U256), Elements::OutputNullDatum => option(option(either(tuple([U2, U256]), either(U1, U4)))), Elements::OutputIsFee => option(bool()), @@ -1015,12 +1031,6 @@ pub fn target_type(jet: Elements) -> AliasedType { } } -#[rustfmt::skip] -#[cfg(any(feature = "arbitrary", test))] -pub(crate) const ALL: [Elements; 460] = [ - Elements::Add16, Elements::Add32, Elements::Add64, Elements::Add8, Elements::All16, Elements::All32, Elements::All64, Elements::All8, Elements::And1, Elements::And16, Elements::And32, Elements::And64, Elements::And8, Elements::AnnexHash, Elements::AssetAmountHash, Elements::Bip0340Verify, Elements::BuildTapbranch, Elements::BuildTapleafSimplicity, Elements::CalculateAsset, Elements::CalculateConfidentialToken, Elements::CalculateExplicitToken, Elements::CalculateIssuanceEntropy, Elements::Ch1, Elements::Ch16, Elements::Ch32, Elements::Ch64, Elements::Ch8, Elements::CheckLockDistance, Elements::CheckLockDuration, Elements::CheckLockHeight, Elements::CheckLockTime, Elements::CheckSigVerify, Elements::Complement1, Elements::Complement16, Elements::Complement32, Elements::Complement64, Elements::Complement8, Elements::CurrentAmount, Elements::CurrentAnnexHash, Elements::CurrentAsset, Elements::CurrentIndex, Elements::CurrentIssuanceAssetAmount, Elements::CurrentIssuanceAssetProof, Elements::CurrentIssuanceTokenAmount, Elements::CurrentIssuanceTokenProof, Elements::CurrentNewIssuanceContract, Elements::CurrentPegin, Elements::CurrentPrevOutpoint, Elements::CurrentReissuanceBlinding, Elements::CurrentReissuanceEntropy, Elements::CurrentScriptHash, Elements::CurrentScriptSigHash, Elements::CurrentSequence, Elements::Decompress, Elements::Decrement16, Elements::Decrement32, Elements::Decrement64, Elements::Decrement8, Elements::DivMod16, Elements::DivMod32, Elements::DivMod64, Elements::DivMod8, Elements::Divide16, Elements::Divide32, Elements::Divide64, Elements::Divide8, Elements::Divides16, Elements::Divides32, Elements::Divides64, Elements::Divides8, Elements::Eq1, Elements::Eq16, Elements::Eq256, Elements::Eq32, Elements::Eq64, Elements::Eq8, Elements::FeAdd, Elements::FeInvert, Elements::FeIsOdd, Elements::FeIsZero, Elements::FeMultiply, Elements::FeMultiplyBeta, Elements::FeNegate, Elements::FeNormalize, Elements::FeSquare, Elements::FeSquareRoot, Elements::FullAdd16, Elements::FullAdd32, Elements::FullAdd64, Elements::FullAdd8, Elements::FullDecrement16, Elements::FullDecrement32, Elements::FullDecrement64, Elements::FullDecrement8, Elements::FullIncrement16, Elements::FullIncrement32, Elements::FullIncrement64, Elements::FullIncrement8, Elements::FullLeftShift16_1, Elements::FullLeftShift16_2, Elements::FullLeftShift16_4, Elements::FullLeftShift16_8, Elements::FullLeftShift32_1, Elements::FullLeftShift32_16, Elements::FullLeftShift32_2, Elements::FullLeftShift32_4, Elements::FullLeftShift32_8, Elements::FullLeftShift64_1, Elements::FullLeftShift64_16, Elements::FullLeftShift64_2, Elements::FullLeftShift64_32, Elements::FullLeftShift64_4, Elements::FullLeftShift64_8, Elements::FullLeftShift8_1, Elements::FullLeftShift8_2, Elements::FullLeftShift8_4, Elements::FullMultiply16, Elements::FullMultiply32, Elements::FullMultiply64, Elements::FullMultiply8, Elements::FullRightShift16_1, Elements::FullRightShift16_2, Elements::FullRightShift16_4, Elements::FullRightShift16_8, Elements::FullRightShift32_1, Elements::FullRightShift32_16, Elements::FullRightShift32_2, Elements::FullRightShift32_4, Elements::FullRightShift32_8, Elements::FullRightShift64_1, Elements::FullRightShift64_16, Elements::FullRightShift64_2, Elements::FullRightShift64_32, Elements::FullRightShift64_4, Elements::FullRightShift64_8, Elements::FullRightShift8_1, Elements::FullRightShift8_2, Elements::FullRightShift8_4, Elements::FullSubtract16, Elements::FullSubtract32, Elements::FullSubtract64, Elements::FullSubtract8, Elements::GeIsOnCurve, Elements::GeNegate, Elements::GejAdd, Elements::GejDouble, Elements::GejEquiv, Elements::GejGeAdd, Elements::GejGeAddEx, Elements::GejGeEquiv, Elements::GejInfinity, Elements::GejIsInfinity, Elements::GejIsOnCurve, Elements::GejNegate, Elements::GejNormalize, Elements::GejRescale, Elements::GejXEquiv, Elements::GejYIsOdd, Elements::Generate, Elements::GenesisBlockHash, Elements::High1, Elements::High16, Elements::High32, Elements::High64, Elements::High8, Elements::Increment16, Elements::Increment32, Elements::Increment64, Elements::Increment8, Elements::InputAmount, Elements::InputAmountsHash, Elements::InputAnnexHash, Elements::InputAnnexesHash, Elements::InputAsset, Elements::InputOutpointsHash, Elements::InputPegin, Elements::InputPrevOutpoint, Elements::InputScriptHash, Elements::InputScriptSigHash, Elements::InputScriptSigsHash, Elements::InputScriptsHash, Elements::InputSequence, Elements::InputSequencesHash, Elements::InputUtxosHash, Elements::InputsHash, Elements::InternalKey, Elements::IsOne16, Elements::IsOne32, Elements::IsOne64, Elements::IsOne8, Elements::IsZero16, Elements::IsZero32, Elements::IsZero64, Elements::IsZero8, Elements::Issuance, Elements::IssuanceAsset, Elements::IssuanceAssetAmount, Elements::IssuanceAssetAmountsHash, Elements::IssuanceAssetProof, Elements::IssuanceBlindingEntropyHash, Elements::IssuanceEntropy, Elements::IssuanceRangeProofsHash, Elements::IssuanceToken, Elements::IssuanceTokenAmount, Elements::IssuanceTokenAmountsHash, Elements::IssuanceTokenProof, Elements::IssuancesHash, Elements::Le16, Elements::Le32, Elements::Le64, Elements::Le8, Elements::LeftExtend16_32, Elements::LeftExtend16_64, Elements::LeftExtend1_16, Elements::LeftExtend1_32, Elements::LeftExtend1_64, Elements::LeftExtend1_8, Elements::LeftExtend32_64, Elements::LeftExtend8_16, Elements::LeftExtend8_32, Elements::LeftExtend8_64, Elements::LeftPadHigh16_32, Elements::LeftPadHigh16_64, Elements::LeftPadHigh1_16, Elements::LeftPadHigh1_32, Elements::LeftPadHigh1_64, Elements::LeftPadHigh1_8, Elements::LeftPadHigh32_64, Elements::LeftPadHigh8_16, Elements::LeftPadHigh8_32, Elements::LeftPadHigh8_64, Elements::LeftPadLow16_32, Elements::LeftPadLow16_64, Elements::LeftPadLow1_16, Elements::LeftPadLow1_32, Elements::LeftPadLow1_64, Elements::LeftPadLow1_8, Elements::LeftPadLow32_64, Elements::LeftPadLow8_16, Elements::LeftPadLow8_32, Elements::LeftPadLow8_64, Elements::LeftRotate16, Elements::LeftRotate32, Elements::LeftRotate64, Elements::LeftRotate8, Elements::LeftShift16, Elements::LeftShift32, Elements::LeftShift64, Elements::LeftShift8, Elements::LeftShiftWith16, Elements::LeftShiftWith32, Elements::LeftShiftWith64, Elements::LeftShiftWith8, Elements::Leftmost16_1, Elements::Leftmost16_2, Elements::Leftmost16_4, Elements::Leftmost16_8, Elements::Leftmost32_1, Elements::Leftmost32_16, Elements::Leftmost32_2, Elements::Leftmost32_4, Elements::Leftmost32_8, Elements::Leftmost64_1, Elements::Leftmost64_16, Elements::Leftmost64_2, Elements::Leftmost64_32, Elements::Leftmost64_4, Elements::Leftmost64_8, Elements::Leftmost8_1, Elements::Leftmost8_2, Elements::Leftmost8_4, Elements::LinearCombination1, Elements::LinearVerify1, Elements::LockTime, Elements::Low1, Elements::Low16, Elements::Low32, Elements::Low64, Elements::Low8, Elements::Lt16, Elements::Lt32, Elements::Lt64, Elements::Lt8, Elements::Maj1, Elements::Maj16, Elements::Maj32, Elements::Maj64, Elements::Maj8, Elements::Max16, Elements::Max32, Elements::Max64, Elements::Max8, Elements::Median16, Elements::Median32, Elements::Median64, Elements::Median8, Elements::Min16, Elements::Min32, Elements::Min64, Elements::Min8, Elements::Modulo16, Elements::Modulo32, Elements::Modulo64, Elements::Modulo8, Elements::Multiply16, Elements::Multiply32, Elements::Multiply64, Elements::Multiply8, Elements::Negate16, Elements::Negate32, Elements::Negate64, Elements::Negate8, Elements::NewIssuanceContract, Elements::NonceHash, Elements::NumInputs, Elements::NumOutputs, Elements::One16, Elements::One32, Elements::One64, Elements::One8, Elements::Or1, Elements::Or16, Elements::Or32, Elements::Or64, Elements::Or8, Elements::OutpointHash, Elements::OutputAmount, Elements::OutputAmountsHash, Elements::OutputAsset, Elements::OutputIsFee, Elements::OutputNonce, Elements::OutputNoncesHash, Elements::OutputNullDatum, Elements::OutputRangeProof, Elements::OutputRangeProofsHash, Elements::OutputScriptHash, Elements::OutputScriptsHash, Elements::OutputSurjectionProof, Elements::OutputSurjectionProofsHash, Elements::OutputsHash, Elements::ParseLock, Elements::ParseSequence, Elements::PointVerify1, Elements::ReissuanceBlinding, Elements::ReissuanceEntropy, Elements::RightExtend16_32, Elements::RightExtend16_64, Elements::RightExtend32_64, Elements::RightExtend8_16, Elements::RightExtend8_32, Elements::RightExtend8_64, Elements::RightPadHigh16_32, Elements::RightPadHigh16_64, Elements::RightPadHigh1_16, Elements::RightPadHigh1_32, Elements::RightPadHigh1_64, Elements::RightPadHigh1_8, Elements::RightPadHigh32_64, Elements::RightPadHigh8_16, Elements::RightPadHigh8_32, Elements::RightPadHigh8_64, Elements::RightPadLow16_32, Elements::RightPadLow16_64, Elements::RightPadLow1_16, Elements::RightPadLow1_32, Elements::RightPadLow1_64, Elements::RightPadLow1_8, Elements::RightPadLow32_64, Elements::RightPadLow8_16, Elements::RightPadLow8_32, Elements::RightPadLow8_64, Elements::RightRotate16, Elements::RightRotate32, Elements::RightRotate64, Elements::RightRotate8, Elements::RightShift16, Elements::RightShift32, Elements::RightShift64, Elements::RightShift8, Elements::RightShiftWith16, Elements::RightShiftWith32, Elements::RightShiftWith64, Elements::RightShiftWith8, Elements::Rightmost16_1, Elements::Rightmost16_2, Elements::Rightmost16_4, Elements::Rightmost16_8, Elements::Rightmost32_1, Elements::Rightmost32_16, Elements::Rightmost32_2, Elements::Rightmost32_4, Elements::Rightmost32_8, Elements::Rightmost64_1, Elements::Rightmost64_16, Elements::Rightmost64_2, Elements::Rightmost64_32, Elements::Rightmost64_4, Elements::Rightmost64_8, Elements::Rightmost8_1, Elements::Rightmost8_2, Elements::Rightmost8_4, Elements::ScalarAdd, Elements::ScalarInvert, Elements::ScalarIsZero, Elements::ScalarMultiply, Elements::ScalarMultiplyLambda, Elements::ScalarNegate, Elements::ScalarNormalize, Elements::ScalarSquare, Elements::Scale, Elements::ScriptCMR, Elements::Sha256Block, Elements::Sha256Ctx8Add1, Elements::Sha256Ctx8Add128, Elements::Sha256Ctx8Add16, Elements::Sha256Ctx8Add2, Elements::Sha256Ctx8Add256, Elements::Sha256Ctx8Add32, Elements::Sha256Ctx8Add4, Elements::Sha256Ctx8Add512, Elements::Sha256Ctx8Add64, Elements::Sha256Ctx8Add8, Elements::Sha256Ctx8AddBuffer511, Elements::Sha256Ctx8Finalize, Elements::Sha256Ctx8Init, Elements::Sha256Iv, Elements::SigAllHash, Elements::Some1, Elements::Some16, Elements::Some32, Elements::Some64, Elements::Some8, Elements::Subtract16, Elements::Subtract32, Elements::Subtract64, Elements::Subtract8, Elements::TapEnvHash, Elements::TapleafHash, Elements::TapleafVersion, Elements::Tappath, Elements::TappathHash, Elements::TotalFee, Elements::TxHash, Elements::TxIsFinal, Elements::TxLockDistance, Elements::TxLockDuration, Elements::TxLockHeight, Elements::TxLockTime, Elements::Verify, Elements::Version, Elements::Xor1, Elements::Xor16, Elements::Xor32, Elements::Xor64, Elements::Xor8, Elements::XorXor1, Elements::XorXor16, Elements::XorXor32, Elements::XorXor64, Elements::XorXor8 -]; - #[cfg(test)] mod tests { use super::*; @@ -1028,7 +1038,7 @@ mod tests { #[test] fn compatible_source_type() { - for jet in ALL { + for jet in Elements::ALL { let resolved_ty = ResolvedType::tuple( source_type(jet) .into_iter() @@ -1044,7 +1054,7 @@ mod tests { #[test] fn compatible_target_type() { - for jet in ALL { + for jet in Elements::ALL { let resolved_ty = target_type(jet).resolve_builtin().unwrap(); let structural_ty = StructuralType::from(&resolved_ty); let simplicity_ty = jet.target_ty().to_final(); diff --git a/src/main.rs b/src/main.rs index b1a6869..660df99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,14 +35,24 @@ fn run() -> Result<(), String> { let wit_text = std::fs::read_to_string(wit_path).map_err(|e| e.to_string())?; let witness = serde_json::from_str::(&wit_text).unwrap(); - let res = satisfy(&prog_text, &witness)?; - let redeem_bytes = res.encode_to_vec(); - println!("{}", Base64Display::new(&redeem_bytes, &STANDARD)); + let program = satisfy(&prog_text, &witness)?; + let (program_bytes, witness_bytes) = program.encode_to_vec(); + println!( + "Program:\n{}", + Base64Display::new(&program_bytes, &STANDARD) + ); + println!( + "Witness:\n{}", + Base64Display::new(&witness_bytes, &STANDARD) + ); } else { // No second argument is provided. Just compile the program. - let prog = compile(&prog_text)?; - let res = prog.encode_to_vec(); - println!("{}", Base64Display::new(&res, &STANDARD)); + let program = compile(&prog_text)?; + let program_bytes = program.encode_to_vec(); + println!( + "Program:\n{}", + Base64Display::new(&program_bytes, &STANDARD) + ); } Ok(()) diff --git a/src/named.rs b/src/named.rs index b4f14d0..b46f69a 100644 --- a/src/named.rs +++ b/src/named.rs @@ -102,6 +102,7 @@ pub fn to_commit_node(node: &ConstructNode) -> Result>, pub fn to_witness_node(node: &ConstructNode, values: &WitnessValues) -> Arc> { struct Populator<'a> { values: &'a WitnessValues, + inference_context: types::Context, } impl<'a, J: Jet> Converter, node::Witness> for Populator<'a> { @@ -144,11 +145,14 @@ pub fn to_witness_node(node: &ConstructNode, values: &WitnessValues) -> Arc::cached_data) .map_witness(Option::>::clone); - Ok(WitnessData::from_inner(inner).unwrap()) + Ok(WitnessData::from_inner(&self.inference_context, inner).unwrap()) } } - let mut populator = Populator { values }; + let mut populator = Populator { + inference_context: types::Context::new(), + values, + }; node.convert::(&mut populator) .unwrap() } @@ -177,12 +181,12 @@ impl From for ConstructData { } impl CoreConstructible for ConstructData { - fn iden() -> Self { - Arrow::iden().into() + fn iden(inference_context: &types::Context) -> Self { + Arrow::iden(inference_context).into() } - fn unit() -> Self { - Arrow::unit().into() + fn unit(inference_context: &types::Context) -> Self { + Arrow::unit(inference_context).into() } fn injl(child: &Self) -> Self { @@ -221,31 +225,35 @@ impl CoreConstructible for ConstructData { Arrow::pair(&left.arrow, &right.arrow).map(Self::from) } - fn fail(entropy: simplicity::FailEntropy) -> Self { - Arrow::fail(entropy).into() + fn fail(inference_context: &types::Context, entropy: FailEntropy) -> Self { + Arrow::fail(inference_context, entropy).into() } - fn const_word(word: Arc) -> Self { - Arrow::const_word(word).into() + fn const_word(inference_context: &types::Context, word: Arc) -> Self { + Arrow::const_word(inference_context, word).into() + } + + fn inference_context(&self) -> &types::Context { + self.arrow.inference_context() } } impl JetConstructible for ConstructData { - fn jet(jet: J) -> Self { - Arrow::jet(jet).into() + fn jet(inference_context: &types::Context, jet: J) -> Self { + Arrow::jet(inference_context, jet).into() } } impl WitnessConstructible for ConstructData { - fn witness(_: WitnessName) -> Self { - Arrow::for_witness().into() + fn witness(inference_context: &types::Context, _: WitnessName) -> Self { + Arrow::witness(inference_context, ()).into() } } /// More constructors for types that implement [`CoreConstructible`]. pub trait CoreExt: CoreConstructible + Sized { - fn h() -> PairBuilder { - PairBuilder::iden() + fn h(inference_context: &types::Context) -> PairBuilder { + PairBuilder::iden(inference_context) } fn o() -> SelectorBuilder { @@ -256,10 +264,10 @@ pub trait CoreExt: CoreConstructible + Sized { SelectorBuilder::default().i() } - fn bit(bit: bool) -> PairBuilder { + fn bit(inference_context: &types::Context, bit: bool) -> PairBuilder { match bit { - false => PairBuilder::unit().injl(), - true => PairBuilder::unit().injr(), + false => PairBuilder::unit(inference_context).injl(), + true => PairBuilder::unit(inference_context).injr(), } } @@ -275,8 +283,12 @@ pub trait CoreExt: CoreConstructible + Sized { /// ------------------- /// comp unit (const v) : A → B /// ``` - fn unit_const_value(value: Arc) -> Self { - Self::comp(&Self::unit(), &Self::const_word(value)).unwrap() + fn unit_const_value(inference_context: &types::Context, value: Arc) -> Self { + Self::comp( + &Self::unit(inference_context), + &Self::const_word(inference_context, value), + ) + .unwrap() } /// `assertl (take s) cmr` always type checks. @@ -300,13 +312,21 @@ pub trait CoreExt: CoreConstructible + Sized { } /// `case false true` always type-checks. - fn case_false_true() -> Self { - Self::case(&Self::bit_false(), &Self::bit_true()).unwrap() + fn case_false_true(inference_context: &types::Context) -> Self { + Self::case( + &Self::bit_false(inference_context), + &Self::bit_true(inference_context), + ) + .unwrap() } /// `case true false` always type-checks. - fn case_true_false() -> Self { - Self::case(&Self::bit_true(), &Self::bit_false()).unwrap() + fn case_true_false(inference_context: &types::Context) -> Self { + Self::case( + &Self::bit_true(inference_context), + &Self::bit_false(inference_context), + ) + .unwrap() } } @@ -345,8 +365,8 @@ impl SelectorBuilder

{ } /// Select the current input value. - pub fn h(self) -> PairBuilder

{ - let mut expr = PairBuilder::iden(); + pub fn h(self, inference_context: &types::Context) -> PairBuilder

{ + let mut expr = PairBuilder::iden(inference_context); for bit in self.selection.into_iter().rev() { match bit { false => expr = expr.take(), @@ -378,8 +398,8 @@ impl PairBuilder

{ /// ------------ /// unit : A → 1 /// ``` - pub fn unit() -> Self { - Self(P::unit()) + pub fn unit(inference_context: &types::Context) -> Self { + Self(P::unit(inference_context)) } /// Create the identity expression. @@ -392,8 +412,8 @@ impl PairBuilder

{ /// ------------ /// iden : A → A /// ``` - pub fn iden() -> Self { - Self(P::iden()) + pub fn iden(inference_context: &types::Context) -> Self { + Self(P::iden(inference_context)) } /// Create the fail expression. @@ -406,8 +426,8 @@ impl PairBuilder

{ /// ------------ /// fail : A → B /// ``` - pub fn fail(entropy: FailEntropy) -> Self { - Self(P::fail(entropy)) + pub fn fail(inference_context: &types::Context, entropy: FailEntropy) -> Self { + Self(P::fail(inference_context, entropy)) } /// Left-inject the expression. @@ -557,8 +577,11 @@ impl PairBuilder

{ /// --------------------------- /// comp unit (const v) : A → B /// ``` - pub fn unit_const_value(value: Arc) -> Self { - Self(P::unit_const_value(value)) + pub fn unit_const_value( + inference_context: &types::Context, + value: Arc, + ) -> Self { + Self(P::unit_const_value(inference_context, value)) } } @@ -573,8 +596,8 @@ impl> PairBuilder

{ /// --------------- /// witness : A → B /// ``` - pub fn witness(witness: WitnessName) -> Self { - Self(P::witness(witness)) + pub fn witness(inference_context: &types::Context, witness: WitnessName) -> Self { + Self(P::witness(inference_context, witness)) } } diff --git a/src/pattern.rs b/src/pattern.rs index d1f67a9..42c396a 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -315,7 +315,11 @@ impl BasePattern { /// This means there are infinitely many translating expressions from `self` to `to`. /// For instance, `iden`, `iden & iden`, `(iden & iden) & iden`, and so on. /// We enforce a unique translation by banning ignore from the `to` pattern. - pub fn translate(&self, to: &Self) -> Option> { + pub fn translate( + &self, + ctx: &simplicity::types::Context, + to: &Self, + ) -> Option> { #[derive(Debug, Clone)] enum Task<'a> { Translate(&'a BasePattern, &'a BasePattern), @@ -345,10 +349,10 @@ impl BasePattern { match to { BasePattern::Ignore => { - output.push(SelectorBuilder::default().h()); + output.push(SelectorBuilder::default().h(ctx)); } BasePattern::Identifier(to_id) => { - output.push(from.get(to_id).map(SelectorBuilder::h)?); + output.push(from.get(to_id).map(|selector| selector.h(ctx))?); } BasePattern::Product(to_left, to_right) => { if to.subsumes(from) { @@ -361,7 +365,7 @@ impl BasePattern { // the pattern `to`. Here, we optimize for the size of the // translating expression and not for the size of the translated // value. - output.push(SelectorBuilder::default().h()); + output.push(SelectorBuilder::default().h(ctx)); } else if let BasePattern::Product(from_left, from_right) = from { if from_right.covers(to) { stack.push(Task::MakeDrop); @@ -470,7 +474,8 @@ mod tests { ]; for (target, expected_expr) in target_expr { - let expr = env.translate(&target).unwrap(); + let ctx = simplicity::types::Context::new(); + let expr = env.translate(&ctx, &target).unwrap(); assert_eq!(expected_expr, expr.as_ref().display_expr().to_string()); } } diff --git a/src/str.rs b/src/str.rs index 2f078b5..37caf4b 100644 --- a/src/str.rs +++ b/src/str.rs @@ -144,7 +144,7 @@ wrapped_string!(JetName); #[cfg(feature = "arbitrary")] impl<'a> arbitrary::Arbitrary<'a> for JetName { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - u.choose(&crate::jet::ALL) + u.choose(&simplicity::jet::Elements::ALL) .map(simplicity::jet::Elements::to_string) .map(Arc::from) .map(Self) diff --git a/src/types.rs b/src/types.rs index f9c4efc..75f2d37 100644 --- a/src/types.rs +++ b/src/types.rs @@ -934,8 +934,11 @@ impl TypeConstructible for StructuralType { impl StructuralType { /// Convert into an unfinalized type that can be used in Simplicity's unification algorithm. - pub fn to_unfinalized(&self) -> simplicity::types::Type { - simplicity::types::Type::from(self.0.clone()) + pub fn to_unfinalized( + &self, + inference_context: &simplicity::types::Context, + ) -> simplicity::types::Type { + simplicity::types::Type::complete(inference_context, self.0.clone()) } } diff --git a/src/value.rs b/src/value.rs index 743a11e..cc93032 100644 --- a/src/value.rs +++ b/src/value.rs @@ -777,8 +777,8 @@ impl TreeLike for StructuralValue { fn as_node(&self) -> Tree { match self.as_ref() { SimValue::Unit => Tree::Nullary, - SimValue::SumL(l) | SimValue::SumR(l) => Tree::Unary(Self(l.clone())), - SimValue::Prod(l, r) => Tree::Binary(Self(l.clone()), Self(r.clone())), + SimValue::Left(l) | SimValue::Right(l) => Tree::Unary(Self(l.clone())), + SimValue::Product(l, r) => Tree::Binary(Self(l.clone()), Self(r.clone())), } } } @@ -797,7 +797,7 @@ impl ValueConstructible for StructuralValue { // Keep this implementation to prevent an infinite loop in ::tuple fn product(left: Self, right: Self) -> Self { - Self(SimValue::prod(left.0, right.0)) + Self(SimValue::product(left.0, right.0)) } fn array>(elements: I) -> Self { @@ -824,8 +824,8 @@ impl ValueConstructible for StructuralValue { impl From> for StructuralValue { fn from(value: Option) -> Self { match value { - None => Self(SimValue::sum_l(SimValue::unit())), - Some(inner) => Self(SimValue::sum_r(inner.0)), + None => Self(SimValue::left(SimValue::unit())), + Some(inner) => Self(SimValue::right(inner.0)), } } } @@ -833,8 +833,8 @@ impl From> for StructuralValue { impl From> for StructuralValue { fn from(value: Either) -> Self { match value { - Either::Left(left) => Self(SimValue::sum_l(left.0)), - Either::Right(right) => Self(SimValue::sum_r(right.0)), + Either::Left(left) => Self(SimValue::left(left.0)), + Either::Right(right) => Self(SimValue::right(right.0)), } } } @@ -842,8 +842,8 @@ impl From> for StructuralValue { impl From for StructuralValue { fn from(value: bool) -> Self { match value { - false => Self(SimValue::sum_l(SimValue::unit())), - true => Self(SimValue::sum_r(SimValue::unit())), + false => Self(SimValue::left(SimValue::unit())), + true => Self(SimValue::right(SimValue::unit())), } } } @@ -859,7 +859,7 @@ impl From for StructuralValue { UIntValue::U32(n) => Self(SimValue::u32(n)), UIntValue::U64(n) => Self(SimValue::u64(n)), UIntValue::U128(n) => Self(SimValue::u128(n)), - UIntValue::U256(n) => Self(SimValue::u256_from_slice(n.as_ref())), + UIntValue::U256(n) => Self(SimValue::u256(n.to_byte_array())), } } }