diff --git a/Cargo.lock b/Cargo.lock index 55f8a999..9d120dc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,11 +4,10 @@ version = 3 [[package]] name = "amplify" -version = "4.7.0" +version = "4.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7147b742325842988dd6c793d55f58df3ae36bccf7d9b6e07db10ab035be343d" +checksum = "448cf0c3afc71439b5f837aac5399a1ef2b223f5f38324dbfb4343deec3b80cc" dependencies = [ - "amplify_apfloat", "amplify_derive", "amplify_num", "amplify_syn", @@ -18,17 +17,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "amplify_apfloat" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695e433882668b55b3d7fb0ba22bf9be66a91abe30d7ca1f1a774f8b90b4db4c" -dependencies = [ - "amplify_num", - "bitflags", - "wasm-bindgen", -] - [[package]] name = "amplify_derive" version = "4.0.1" @@ -94,12 +82,12 @@ dependencies = [ [[package]] name = "ascii-armor" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4966ac403dc4a666d8131dfe4df684f45acc68d4c7e768db89c463aa5617910" +checksum = "6ca6f0044fabe840af8db8de7f3bff0c85af2a5c2a173780248c1716e86f5cc1" dependencies = [ "amplify", - "baid64", + "baid64 0.3.0", "base85", "sha2", "strict_encoding", @@ -123,6 +111,18 @@ dependencies = [ "sha2", ] +[[package]] +name = "baid64" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30acc16368c00c4d3ce4526d0c1528e22d75814534b3dba97e871aa5f8395697" +dependencies = [ + "amplify", + "base64", + "mnemonic", + "sha2", +] + [[package]] name = "base64" version = "0.22.1" @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "bitcoin-io" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" [[package]] name = "bitcoin_hashes" @@ -154,12 +154,6 @@ dependencies = [ "hex-conservative", ] -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - [[package]] name = "block-buffer" version = "0.10.4" @@ -171,7 +165,7 @@ dependencies = [ [[package]] name = "bp-consensus" -version = "0.11.0-beta.9" +version = "0.12.0-alpha.1" dependencies = [ "amplify", "chrono", @@ -184,7 +178,7 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.11.0-beta.9" +version = "0.12.0-alpha.1" dependencies = [ "amplify", "bp-consensus", @@ -203,7 +197,7 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.11.0-beta.9" +version = "0.12.0-alpha.1" dependencies = [ "amplify", "base85", @@ -216,10 +210,10 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.11.0-beta.9" +version = "0.12.0-alpha.1" dependencies = [ "amplify", - "baid64", + "baid64 0.2.2", "bp-consensus", "bp-dbc", "commit_verify", @@ -243,9 +237,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" dependencies = [ "shlex", ] @@ -272,9 +266,8 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.11.0-beta.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea07c5ad73a637276dc4f8a957f8285764018d45bdefef35eb9137f32d0e3c81" +version = "0.12.0-alpha.2" +source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.12#a625ed95943ba862b7f7b975d34ed837b2a3aba4" dependencies = [ "amplify", "amplify_syn", @@ -285,9 +278,8 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.11.0-beta.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf08c4941e147937551f6a3d370552d67f98cf72c9eb18948142596beadd31e" +version = "0.12.0-alpha.2" +source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.12#a625ed95943ba862b7f7b975d34ed837b2a3aba4" dependencies = [ "amplify", "commit_encoding_derive", @@ -318,19 +310,13 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "crypto-common" version = "0.1.6" @@ -380,21 +366,11 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "heck" @@ -455,9 +431,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "log" @@ -467,9 +443,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "minicov" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def6d99771d7c499c26ad4d40eb6645eafd3a1553b35fc26ea5a489a45e82d9a" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" dependencies = [ "cc", "walkdir", @@ -606,22 +582,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -653,30 +629,25 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.11.0-beta.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec071f3b3153217f1cb2bca5ba7ac87eeafc446cb35a5c0643dec33495a37244" -dependencies = [ - "amplify_derive", -] +version = "0.12.0-alpha.2" +source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.12#a625ed95943ba862b7f7b975d34ed837b2a3aba4" [[package]] name = "strict_encoding" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69b4893cf054e129d5288a565102124520d7b94eb9589d1e78202abc7e2092d" +checksum = "3b71b5ba13c289a8b6f0a3ed4abebb92ce2d57b805b1db26e543b4ac26237870" dependencies = [ "amplify", - "half", "strict_encoding_derive", "wasm-bindgen", ] [[package]] name = "strict_encoding_derive" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4f9b678862372f8e439bcaafc27df7610ea93b06d2deb6244dec0af4259ce6" +checksum = "34e3bc6e4a2450420b4dbfb6929d9ce005e8c36cf73bf215db99f0d09c9fa79f" dependencies = [ "amplify_syn", "heck", @@ -687,14 +658,13 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bae7475fc901144d8a35d25e36d76aa020b840f233d60532d6d52318718781b" +checksum = "ef2dcdbb3f239b310f3d07e81e8f4da3b5ffe17da980a360ca029e9bc263f049" dependencies = [ "amplify", "ascii-armor", - "baid64", - "half", + "baid64 0.3.0", "indexmap", "sha2", "strict_encoding", @@ -725,9 +695,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -736,22 +706,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -774,9 +744,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vesper-lang" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72ebd3b32f16ee8ace2bd3058c2bfa0f4820992bd4ea86e73ba228bb13dd2b0" +checksum = "cd2b7e3e27aeb0524204e58042f6e4531a720745d1b1a3978d3a084f1885f63d" dependencies = [ "amplify", "strict_encoding", @@ -820,7 +790,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -854,7 +824,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -888,7 +858,7 @@ checksum = "c97b2ef2c8d627381e51c071c2ab328eac606d3f69dd82bcbca20a9e389d95f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1010,5 +980,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index 9644590d..52f64ef4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ default-members = [ ] [workspace.package] -version = "0.11.0-beta.9" +version = "0.12.0-alpha.1" authors = ["Dr Maxim Orlovsky "] homepage = "https://github.com/BP-WG" repository = "https://github.com/BP-WG/bp-core" @@ -23,13 +23,13 @@ license = "Apache-2.0" [workspace.dependencies] amplify = "4.7.0" -strict_encoding = "2.7.0" +strict_encoding = "2.7.2" strict_types = "2.7.2" -commit_verify = "0.11.0-beta.9" -single_use_seals = "0.11.0-beta.9" -bp-consensus = { version = "0.11.0-beta.9", path = "./consensus" } -bp-dbc = { version = "0.11.0-beta.9", path = "./dbc" } -bp-seals = { version = "0.11.0-beta.9", path = "./seals" } +commit_verify = "0.12.0-alpha.2" +single_use_seals = "0.12.0-alpha.2" +bp-consensus = { version = "0.12.0-alpha.1", path = "./consensus" } +bp-dbc = { version = "0.12.0-alpha.1", path = "./dbc" } +bp-seals = { version = "0.12.0-alpha.1", path = "./seals" } secp256k1 = { version = "0.30.0", features = ["global-context", "rand"] } serde_crate = { package = "serde", version = "1", features = ["derive"] } @@ -89,3 +89,7 @@ wasm-bindgen-test = "0.3" [package.metadata.docs.rs] features = ["all"] + +[patch.crates-io] +commit_verify = { git = "https://github.com/LNP-BP/client_side_validation", branch = "v0.12" } +single_use_seals = { git = "https://github.com/LNP-BP/client_side_validation", branch = "v0.12" } diff --git a/consensus/src/stl.rs b/consensus/src/stl.rs index cb782388..f4b0c07f 100644 --- a/consensus/src/stl.rs +++ b/consensus/src/stl.rs @@ -32,9 +32,9 @@ use crate::{ }; pub const LIB_ID_BP_TX: &str = - "stl:9WwTYiP2-OadKCZP-cR0bJ!Y-qruINYX-bXZFj8Y-fsQoGgo#signal-color-cipher"; + "stl:9WwTYiP2-OadKCZP-cR0bJ~Y-qruINYX-bXZFj8Y-fsQoGgo#signal-color-cipher"; pub const LIB_ID_BP_CONSENSUS: &str = - "stl:q7G95wzt-SxT2BMV-t!PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda"; + "stl:q7G95wzt-SxT2BMV-t~PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda"; #[deprecated(since = "0.10.8", note = "use _bp_tx_stl instead")] fn _bitcoin_stl() -> Result { _bp_tx_stl() } diff --git a/dbc/src/proof.rs b/dbc/src/proof.rs index 8c17896f..e011861d 100644 --- a/dbc/src/proof.rs +++ b/dbc/src/proof.rs @@ -35,6 +35,11 @@ use crate::LIB_NAME_BPCORE; pub struct MethodParseError(pub String); /// Method of DBC construction. +/// +/// Method defines a set of parameters used by a single-use seal, such as: +/// - selection of bitcoin input; +/// - commitment algorithm; +/// - used hash functions. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[cfg_attr( feature = "serde", @@ -46,13 +51,13 @@ pub struct MethodParseError(pub String); #[repr(u8)] pub enum Method { /// OP_RETURN commitment present in the first OP_RETURN-containing - /// transaction output. + /// transaction output, made with tagged SHA256 hash function. #[display("opret1st")] #[strict_type(dumb)] OpretFirst = 0x00, /// Taproot-based OP_RETURN commitment present in the first Taproot - /// transaction output. + /// transaction output, made with tagged SHA256 hash function. #[display("tapret1st")] TapretFirst = 0x01, } @@ -75,7 +80,7 @@ pub trait Proof: Clone + Eq + Debug + StrictSerialize + StrictDeserialize + Stri const METHOD: Method; /// Verification error. - type Error: Error; + type Error: Clone + Error; /// Verifies DBC proof against the provided transaction. fn verify(&self, msg: &mpc::Commitment, tx: &Tx) -> Result<(), Self::Error>; diff --git a/seals/src/lib.rs b/seals/src/lib.rs index ee627686..69db428b 100644 --- a/seals/src/lib.rs +++ b/seals/src/lib.rs @@ -27,7 +27,7 @@ unused_mut, unused_imports, dead_code, - missing_docs + // missing_docs )] #![cfg_attr(docsrs, feature(doc_auto_cfg))] @@ -43,8 +43,8 @@ extern crate commit_verify; #[macro_use] extern crate serde_crate as serde; -pub mod resolver; -pub mod txout; +mod txout; mod secret; pub use secret::SecretSeal; +pub use txout::{Anchor, Noise, TxoSeal, TxoSealExt}; diff --git a/seals/src/resolver.rs b/seals/src/resolver.rs deleted file mode 100644 index 481a1db2..00000000 --- a/seals/src/resolver.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! API for resolving single-use-seals. - -use bc::{Tx, Txid}; - -/// Error resolving single-use-seal -#[derive(Debug, Display)] -#[display(doc_comments)] -pub enum Error { - /// Resolver implementation-specific error. - #[display(inner)] - Connection(Box), - - /// transaction with id {0} is not known to the resolver. - UnknownTx(Txid), -} - -/// API which must be provided by a resolver to operate with single-use-seal. -pub trait Resolver { - /// Return transaction data for a given transaction id. - fn tx_by_id(&self, txid: Txid) -> Result; -} diff --git a/seals/src/txout.rs b/seals/src/txout.rs new file mode 100644 index 00000000..9bd7de84 --- /dev/null +++ b/seals/src/txout.rs @@ -0,0 +1,154 @@ +// Bitcoin protocol single-use-seals library. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2024 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Bitcoin single-use-seals defined by a transaction output and closed by +//! spending that output ("TxOut seals"). + +use core::fmt::Debug; +use core::marker::PhantomData; + +use amplify::Bytes; +use bc::{Outpoint, Tx, Txid}; +use commit_verify::mpc::{self, ProtocolId}; +use commit_verify::ReservedBytes; +use single_use_seals::{ClientSideWitness, PublishedWitness, SealWitness, SingleUseSeal}; +use strict_encoding::StrictDumb; + +use crate::SecretSeal; + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = dbc::LIB_NAME_BPCORE)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct Noise(Bytes<68>); + +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = dbc::LIB_NAME_BPCORE)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] +pub struct Anchor { + pub mpc_proof: mpc::MerkleProof, + pub dbc_proof: D, + #[cfg_attr(feature = "serde", serde(skip))] + // TODO: This should become an option + pub fallback_proof: ReservedBytes<1>, +} + +pub struct Proof { + pub mpc_commit: mpc::Commitment, + pub dbc_proof: D, +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = dbc::LIB_NAME_BPCORE, tags = custom)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", untagged) +)] +pub enum TxoSealExt { + #[display("~")] + #[strict_type(tag = 0)] + Noise(Noise), + + #[display(inner)] + #[strict_type(tag = 1)] + Fallback(Outpoint), +} + +impl StrictDumb for TxoSealExt { + fn strict_dumb() -> Self { TxoSealExt::Noise(Noise::from(Bytes::from_byte_array([0u8; 68]))) } +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[display("{primary}/{secondary}")] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = dbc::LIB_NAME_BPCORE)] +#[derive(CommitEncode)] +#[commit_encode(strategy = strict, id = SecretSeal)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +pub struct TxoSeal { + pub primary: Outpoint, + pub secondary: TxoSealExt, + #[strict_type(skip)] + #[cfg_attr(feature = "serde", serde(skip))] + _phantom: PhantomData, +} + +impl SingleUseSeal for TxoSeal { + type Message = Proof; + type PubWitness = Tx; + type CliWitness = Anchor; + + fn is_included(&self, witness: &SealWitness) -> bool { + let mut inputs = witness.published.inputs(); + match self.secondary { + TxoSealExt::Noise(_) => { + inputs.any(|input| input.prev_output == self.primary) + // TODO: && witness.client.fallback_proof.is_none() + } + TxoSealExt::Fallback(fallback) => { + inputs.any(|input| input.prev_output == fallback) + // TODO: && witness.client.fallback_proof.is_some() + } + } + } +} + +// TODO: It's not just a transaction, it should be an SPV proof +impl PublishedWitness> for Tx { + type PubId = Txid; + type Error = D::Error; + + fn pub_id(&self) -> Txid { self.txid() } + fn verify_commitment(&self, proof: Proof) -> Result<(), Self::Error> { + proof.dbc_proof.verify(&proof.mpc_commit, self) + } +} + +impl ClientSideWitness for Anchor { + type Message = (ProtocolId, mpc::Message); + type Seal = TxoSeal; + type Error = mpc::InvalidProof; + + fn convolve_commit( + &self, + (protocol_id, message): (ProtocolId, mpc::Message), + ) -> Result, Self::Error> { + // TODO: Verify fallback proof + // if let Some(_fallback_proof) = self.fallback_proof { + // } + let mpc_commit = self.mpc_proof.convolve(protocol_id, message)?; + Ok(Proof { + mpc_commit, + dbc_proof: self.dbc_proof.clone(), + }) + } +} diff --git a/seals/src/txout/blind.rs b/seals/src/txout/blind.rs deleted file mode 100644 index 17240d51..00000000 --- a/seals/src/txout/blind.rs +++ /dev/null @@ -1,466 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! TxOut seals which are blinded with additional entropy. - -use std::fmt::{self, Debug, Display, Formatter}; -use std::hash::Hash; -use std::str::FromStr; - -use amplify::hex; -use bc::{Outpoint, Txid, Vout}; -use commit_verify::{CommitId, Conceal}; -use dbc::MethodParseError; -use rand::{thread_rng, RngCore}; -use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; - -use super::{CloseMethod, WitnessVoutError}; -use crate::txout::{SealTxid, TxPtr, TxoSeal}; -use crate::SecretSeal; - -/// Seal type which can be blinded and chained with other seals. -pub type ChainBlindSeal = BlindSeal; -/// Seal type which can be blinded, but can't be chained with other seals. -pub type SingleBlindSeal = BlindSeal; - -/// Revealed seal definition which may point to a witness transactions and -/// contains blinding data. -/// -/// Revealed seal means that the seal definition containing explicit information -/// about the bitcoin transaction output. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = dbc::LIB_NAME_BPCORE)] -#[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = SecretSeal)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct BlindSeal { - /// Commitment to the specific seal close method [`CloseMethod`] which must - /// be used to close this seal. - pub method: CloseMethod, - - /// Txid of the seal definition. - /// - /// It may be missed in situations when ID of a transaction is not known, - /// but the transaction still can be identified by some other means (for - /// instance it is a transaction spending specific outpoint, like other - /// seal definition). - pub txid: Id, - - /// Tx output number, which should be always known. - pub vout: Vout, - - /// Blinding factor providing confidentiality of the seal definition. - /// Prevents rainbow table bruteforce attack based on the existing - /// blockchain txid set. - pub blinding: u64, -} - -impl Conceal for BlindSeal { - type Concealed = SecretSeal; - - #[inline] - fn conceal(&self) -> Self::Concealed { self.commit_id() } -} - -impl TryFrom<&BlindSeal> for Outpoint { - type Error = WitnessVoutError; - - #[inline] - fn try_from(reveal: &BlindSeal) -> Result { - reveal.txid.map_to_outpoint(reveal.vout).ok_or(WitnessVoutError) - } -} - -impl TryFrom> for Outpoint { - type Error = WitnessVoutError; - - #[inline] - fn try_from(reveal: BlindSeal) -> Result { - Outpoint::try_from(&reveal) - } -} - -impl From<&BlindSeal> for Outpoint { - #[inline] - fn from(reveal: &BlindSeal) -> Self { Outpoint::new(reveal.txid, reveal.vout) } -} - -impl From> for Outpoint { - #[inline] - fn from(reveal: BlindSeal) -> Self { Outpoint::from(&reveal) } -} - -impl TxoSeal for BlindSeal { - #[inline] - fn method(&self) -> CloseMethod { self.method } - - #[inline] - fn txid(&self) -> Option { self.txid.txid() } - - #[inline] - fn vout(&self) -> Vout { self.vout } - - #[inline] - fn outpoint(&self) -> Option { self.txid.map_to_outpoint(self.vout) } - - #[inline] - fn txid_or(&self, default_txid: Txid) -> Txid { self.txid.txid_or(default_txid) } - - #[inline] - fn outpoint_or(&self, default_txid: Txid) -> Outpoint { - Outpoint::new(self.txid.txid_or(default_txid), self.vout) - } -} - -impl BlindSeal { - /// Creates new seal using TapretFirst closing method for the provided - /// outpoint. Uses `thread_rng` to initialize blinding factor. - pub fn tapret_first_rand_from(outpoint: Outpoint) -> Self { - BlindSeal::tapret_first_rand(outpoint.txid, outpoint.vout) - } - - /// Creates new seal using OpretFirst closing method for the provided - /// outpoint. Uses `thread_rng` to initialize blinding factor. - pub fn opret_first_rand_from(outpoint: Outpoint) -> Self { - BlindSeal::opret_first_rand(outpoint.txid, outpoint.vout) - } - - /// Creates new seal using TapretFirst closing method for the provided - /// outpoint. Uses `thread_rng` to initialize blinding factor. - pub fn tapret_first_rand(txid: impl Into, vout: impl Into) -> Self { - BlindSeal::with_rng(CloseMethod::TapretFirst, txid, vout, &mut thread_rng()) - } - - /// Creates new seal using OpretFirst closing method for the provided - /// outpoint. Uses `thread_rng` to initialize blinding factor. - pub fn opret_first_rand(txid: impl Into, vout: impl Into) -> Self { - BlindSeal::with_rng(CloseMethod::OpretFirst, txid, vout, &mut thread_rng()) - } -} - -impl BlindSeal { - /// Creates new seal for the provided outpoint and seal closing method. Uses - /// `thread_rng` to initialize blinding factor. - pub fn new_random(method: CloseMethod, txid: impl Into, vout: impl Into) -> Self { - BlindSeal::with_rng(method, txid, vout, &mut thread_rng()) - } - - /// Creates new seal for the provided outpoint and seal closing method. Uses - /// provided random number generator to create a new blinding factor. - pub fn with_rng( - method: CloseMethod, - txid: impl Into, - vout: impl Into, - rng: &mut impl RngCore, - ) -> Self { - BlindSeal { - method, - txid: txid.into(), - vout: vout.into(), - blinding: rng.next_u64(), - } - } - - /// Reconstructs previously defined seal pointing to a witness transaction - /// of another seal with a given method, witness transaction output number - /// and previously generated blinding factor value. - pub fn with_blinding( - method: CloseMethod, - txid: impl Into, - vout: impl Into, - blinding: u64, - ) -> Self { - BlindSeal { - method, - txid: txid.into(), - vout: vout.into(), - blinding, - } - } -} - -impl BlindSeal { - /// Creates new seal pointing to a witness transaction of another seal. - /// Takes seal closing method and witness transaction output number as - /// arguments. Uses `thread_rng` to initialize blinding factor. - #[inline] - pub fn new_random_vout(method: CloseMethod, vout: impl Into) -> Self { - Self { - method, - blinding: thread_rng().next_u64(), - txid: TxPtr::WitnessTx, - vout: vout.into(), - } - } - - /// Reconstructs previously defined seal pointing to a witness transaction - /// of another seal with a given method, witness transaction output number - /// and previously generated blinding factor value.. - pub fn with_blinded_vout(method: CloseMethod, vout: impl Into, blinding: u64) -> Self { - BlindSeal { - method, - txid: TxPtr::WitnessTx, - vout: vout.into(), - blinding, - } - } -} - -impl BlindSeal { - /// Converts `BlindSeal` into `BlindSeal`. - pub fn transmutate(self) -> BlindSeal { - BlindSeal::with_blinding(self.method, self.txid, self.vout, self.blinding) - } - - /// Converts seal into a transaction outpoint. - #[inline] - pub fn to_outpoint(&self) -> Outpoint { Outpoint::new(self.txid, self.vout) } -} - -impl BlindSeal { - /// Converts `BlindSeal` into `BlindSeal`. - pub fn resolve(self, txid: Txid) -> BlindSeal { - BlindSeal::with_blinding(self.method, self.txid().unwrap_or(txid), self.vout, self.blinding) - } -} - -/// Errors happening during parsing string representation of different forms of -/// single-use-seals -#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum ParseError { - /// single-use-seal must start with method name (e.g. 'tapret1st' etc) - MethodRequired, - - /// full transaction id is required for the seal specification - TxidRequired, - - /// blinding factor must be specified after `#` - BlindingRequired, - - /// wrong seal close method id - #[display(inner)] - #[from] - WrongMethod(MethodParseError), - - /// unable to parse blinding value; it must be a hexadecimal string - /// starting with `0x` - WrongBlinding, - - /// unable to parse transaction id value; it must be 64-character - /// hexadecimal string, however {0} - WrongTxid(hex::Error), - - /// unable to parse transaction vout value; it must be a decimal unsigned - /// integer - WrongVout, - - /// wrong structure of seal string representation - WrongStructure, - - /// blinding secret must be represented by a 64-bit hexadecimal value - /// starting with `0x` and not with a decimal - NonHexBlinding, -} - -impl FromStr for BlindSeal { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - let mut split = s.split(&[':', '#'][..]); - match (split.next(), split.next(), split.next(), split.next(), split.next()) { - (Some("~"), ..) | (Some(""), ..) => Err(ParseError::MethodRequired), - (Some(_), Some(""), ..) => Err(ParseError::TxidRequired), - (Some(_), Some(_), None, ..) if s.contains(':') => Err(ParseError::BlindingRequired), - (Some(_), Some(_), Some(_), Some(blinding), None) if !blinding.starts_with("0x") => { - Err(ParseError::NonHexBlinding) - } - (Some(method), Some(txid), Some(vout), Some(blinding), None) => Ok(BlindSeal { - method: method.parse()?, - blinding: u64::from_str_radix(blinding.trim_start_matches("0x"), 16) - .map_err(|_| ParseError::WrongBlinding)?, - txid: Id::from_str(txid).map_err(ParseError::WrongTxid)?, - vout: vout.parse().map_err(|_| ParseError::WrongVout)?, - }), - _ => Err(ParseError::WrongStructure), - } - } -} - -impl Display for BlindSeal { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}:{}#{:#010x}", self.method, self.txid, self.vout, self.blinding) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn blind_seal_str() { - let mut outpoint_reveal = BlindSeal { - method: CloseMethod::TapretFirst, - blinding: 0x31bbed7e7b2d, - txid: TxPtr::Txid( - Txid::from_str("646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839") - .unwrap(), - ), - vout: Vout::from(21), - }; - - let s = outpoint_reveal.to_string(); - assert_eq!( - &s, - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:21#\ - 0x31bbed7e7b2d" - ); - // round-trip - assert_eq!(ChainBlindSeal::from_str(&s).unwrap(), outpoint_reveal); - - outpoint_reveal.txid = TxPtr::WitnessTx; - let s = outpoint_reveal.to_string(); - assert_eq!(&s, "tapret1st:~:21#0x31bbed7e7b2d"); - // round-trip - assert_eq!(ChainBlindSeal::from_str(&s).unwrap(), outpoint_reveal); - - // wrong method - assert_eq!( - ChainBlindSeal::from_str( - "tapret:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:0x765#\ - 0x78ca95" - ), - Err(ParseError::WrongMethod(MethodParseError(s!("tapret")))) - ); - - // wrong vout value - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:0x765#\ - 0x78ca95" - ), - Err(ParseError::WrongVout) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:i9#\ - 0x78ca95" - ), - Err(ParseError::WrongVout) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:-5#\ - 0x78ca95" - ), - Err(ParseError::WrongVout) - ); - - // wrong blinding secret value - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:5#\ - 0x78cs" - ), - Err(ParseError::WrongBlinding) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:5#\ - 78ca95" - ), - Err(ParseError::NonHexBlinding) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:5#857" - ), - Err(ParseError::NonHexBlinding) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:5#-5" - ), - Err(ParseError::NonHexBlinding) - ); - - // wrong txid value - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d607719dfd820551fb773e4dc8c4ed67965a8d1fae839:5#\ - 0x78ca69" - ), - Err(ParseError::WrongTxid(hex::Error::OddLengthString(63))) - ); - assert_eq!( - ChainBlindSeal::from_str("tapret1st:rvgbdg:5#0x78ca69"), - Err(ParseError::WrongTxid(hex::Error::InvalidChar(b'r'))) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:10@646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:5#\ - 0x78ca69" - ), - Err(ParseError::WrongTxid(hex::Error::OddLengthString(67))) - ); - - // wrong structure - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:1" - ), - Err(ParseError::WrongStructure) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839#0x78ca" - ), - Err(ParseError::WrongStructure) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839" - ), - Err(ParseError::BlindingRequired) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839##\ - 0x78ca" - ), - Err(ParseError::WrongVout) - ); - assert_eq!( - ChainBlindSeal::from_str( - "tapret1st:646ca5c1062619e2a2d60771c9dfd820551fb773e4dc8c4ed67965a8d1fae839:#\ - 0x78ca95" - ), - Err(ParseError::WrongVout) - ); - assert_eq!( - ChainBlindSeal::from_str("tapret1st:_:5#0x78ca"), - Err(ParseError::WrongTxid(hex::Error::OddLengthString(1))) - ); - assert_eq!(ChainBlindSeal::from_str(":5#0x78ca"), Err(ParseError::MethodRequired)); - assert_eq!(ChainBlindSeal::from_str("~:5#0x78ca"), Err(ParseError::MethodRequired)); - } -} diff --git a/seals/src/txout/error.rs b/seals/src/txout/error.rs deleted file mode 100644 index d8f733ba..00000000 --- a/seals/src/txout/error.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::error::Error; - -use bc::Outpoint; - -/// Seal verification errors. -#[derive(Clone, PartialEq, Eq, Debug, Display, From, Error)] -#[display(doc_comments)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum VerifyError { - /// seals provided for a batch verification have inconsistent close method. - InconsistentCloseMethod, - - /// the provided witness transaction does not closes seal {0}. - WitnessNotClosingSeal(Outpoint), - - /// seal lacks witness transaction id information. - NoWitnessTxid, - - /// invalid DBC commitment. - #[display(inner)] - Dbc(E), -} - -/// Error happening if the seal data holds only witness transaction output -/// number and thus can't be used alone for constructing full bitcoin -/// transaction output data which must include the witness transaction id -/// (unknown to the seal). -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error)] -#[display("witness txid is unknown; unable to reconstruct full outpoint data")] -pub struct WitnessVoutError; diff --git a/seals/src/txout/explicit.rs b/seals/src/txout/explicit.rs deleted file mode 100644 index 22a58bda..00000000 --- a/seals/src/txout/explicit.rs +++ /dev/null @@ -1,187 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! TxOut single-use-seals. - -use std::fmt::{self, Display, Formatter}; -use std::str::FromStr; - -use amplify::hex; -use bc::{Outpoint, Txid, Vout}; -use dbc::MethodParseError; - -use crate::txout::seal::{SealTxid, TxPtr}; -use crate::txout::{CloseMethod, TxoSeal, WitnessVoutError}; - -/// Revealed seal definition which may point to a witness transactions and does -/// not contain blinding data. -/// -/// These data are not used within RGB contract data, thus we do not have a -/// commitment and conceal procedures (since without knowing a blinding factor -/// we can't perform them). -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = dbc::LIB_NAME_BPCORE)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct ExplicitSeal { - /// Commitment to the specific seal close method [`CloseMethod`] which must - /// be used to close this seal. - pub method: CloseMethod, - - /// Txid of the seal definition. - /// - /// It may be missed in situations when ID of a transaction is not known, - /// but the transaction still can be identified by some other means (for - /// instance it is a transaction spending specific outpoint, like other - /// seal definition). - pub txid: Id, - - /// Tx output number, which should be always known. - pub vout: Vout, -} - -impl TryFrom<&ExplicitSeal> for Outpoint { - type Error = WitnessVoutError; - - #[inline] - fn try_from(reveal: &ExplicitSeal) -> Result { - reveal.txid.map_to_outpoint(reveal.vout).ok_or(WitnessVoutError) - } -} - -impl TryFrom> for Outpoint { - type Error = WitnessVoutError; - - #[inline] - fn try_from(reveal: ExplicitSeal) -> Result { - Outpoint::try_from(&reveal) - } -} - -impl From<&ExplicitSeal> for Outpoint { - fn from(seal: &ExplicitSeal) -> Self { Outpoint::new(seal.txid, seal.vout) } -} - -impl From> for Outpoint { - fn from(seal: ExplicitSeal) -> Self { Outpoint::from(&seal) } -} - -impl TxoSeal for ExplicitSeal { - #[inline] - fn method(&self) -> CloseMethod { self.method } - - #[inline] - fn txid(&self) -> Option { self.txid.txid() } - - #[inline] - fn vout(&self) -> Vout { self.vout } - - #[inline] - fn outpoint(&self) -> Option { self.txid.map_to_outpoint(self.vout) } - - #[inline] - fn txid_or(&self, default_txid: Txid) -> Txid { self.txid.txid_or(default_txid) } - - #[inline] - fn outpoint_or(&self, default_txid: Txid) -> Outpoint { - Outpoint::new(self.txid.txid_or(default_txid), self.vout) - } -} - -impl ExplicitSeal { - /// Constructs seal for the provided outpoint and seal closing method. - #[inline] - pub fn new(method: CloseMethod, outpoint: Outpoint) -> ExplicitSeal { - Self { - method, - txid: Id::from(outpoint.txid), - vout: outpoint.vout, - } - } - - /// Constructs seal. - #[inline] - pub fn with(method: CloseMethod, txid: Id, vout: impl Into) -> ExplicitSeal { - ExplicitSeal { - method, - txid, - vout: vout.into(), - } - } -} - -impl ExplicitSeal { - /// Converts seal into a transaction outpoint. - #[inline] - pub fn to_outpoint(&self) -> Outpoint { Outpoint::new(self.txid, self.vout) } -} - -/// Errors happening during parsing string representation of different forms of -/// single-use-seals -#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum ParseError { - /// single-use-seal must start with method name (e.g. 'tapret1st' etc) - MethodRequired, - - /// full transaction id is required for the seal specification - TxidRequired, - - /// wrong seal close method id - #[display(inner)] - #[from] - WrongMethod(MethodParseError), - - /// unable to parse transaction id value; it must be 64-character - /// hexadecimal string, however {0} - WrongTxid(hex::Error), - - /// unable to parse transaction vout value; it must be a decimal unsigned - /// integer - WrongVout, - - /// wrong structure of seal string representation - WrongStructure, -} - -impl FromStr for ExplicitSeal { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - let mut split = s.split(&[':', '#'][..]); - match (split.next(), split.next(), split.next(), split.next()) { - (Some("~"), ..) | (Some(""), ..) => Err(ParseError::MethodRequired), - (Some(_), Some(""), ..) => Err(ParseError::TxidRequired), - (Some(method), Some(txid), Some(vout), None) => Ok(ExplicitSeal { - method: method.parse()?, - txid: Id::from_str(txid).map_err(ParseError::WrongTxid)?, - vout: vout.parse().map_err(|_| ParseError::WrongVout)?, - }), - _ => Err(ParseError::WrongStructure), - } - } -} - -impl Display for ExplicitSeal { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}:{}", self.method, self.txid, self.vout,) - } -} diff --git a/seals/src/txout/mod.rs b/seals/src/txout/mod.rs deleted file mode 100644 index 925b0b4e..00000000 --- a/seals/src/txout/mod.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Bitcoin single-use-seals defined by a transaction output and closed by -//! spending that output ("TxOut seals"). - -pub mod blind; -mod error; -pub mod explicit; -mod seal; -mod witness; - -pub use blind::{BlindSeal, ChainBlindSeal, SingleBlindSeal}; -pub use error::{VerifyError, WitnessVoutError}; -pub use explicit::ExplicitSeal; -pub use seal::{CloseMethod, SealTxid, TxPtr, TxoSeal}; -pub use witness::Witness; diff --git a/seals/src/txout/seal.rs b/seals/src/txout/seal.rs deleted file mode 100644 index a3f18acc..00000000 --- a/seals/src/txout/seal.rs +++ /dev/null @@ -1,148 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::fmt::{Debug, Display}; -use std::hash::Hash; -use std::str::FromStr; - -use amplify::hex; -use bc::{Outpoint, Txid, Vout}; -use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; - -/// Method for closing single-use-seals. -pub type CloseMethod = dbc::Method; - -/// Methods common for all transaction-output based seal types. -pub trait TxoSeal { - /// Returns method which must be used for seal closing. - fn method(&self) -> CloseMethod; - - /// Returns [`Txid`] part of the seal definition, if known. - fn txid(&self) -> Option; - - /// Returns transaction output number containing the defined seal. - fn vout(&self) -> Vout; - - /// Returns [`Outpoint`] defining the seal, if txid is known. - fn outpoint(&self) -> Option; - - /// Returns [`Txid`] part of the seal definition, if known, or the provided - /// `default_txid`. - fn txid_or(&self, default_txid: Txid) -> Txid; - - /// Returns [`Outpoint`] defining the seal, if txid is known, or constructs - /// one using the provided `default_txid`. - fn outpoint_or(&self, default_txid: Txid) -> Outpoint; -} - -/// Marker trait for variants of seal transaction id. -pub trait SealTxid: - Copy - + Eq - + Ord - + Hash - + Debug - + Display - + FromStr - + StrictDumb - + StrictEncode - + StrictDecode - + From -{ - /// Returns transaction id, if known. - fn txid(&self) -> Option; - /// Returns transaction id, if known, or some default value otherwise. - fn txid_or(&self, default: Txid) -> Txid; - /// Converts to outpoint, if the transaction id is known. - fn map_to_outpoint(&self, vout: impl Into) -> Option; -} - -impl SealTxid for Txid { - fn txid(&self) -> Option { Some(*self) } - fn txid_or(&self, _default: Txid) -> Txid { *self } - fn map_to_outpoint(&self, vout: impl Into) -> Option { - Some(Outpoint::new(*self, vout.into())) - } -} - -/// Transaction pointer which can be used to construct graph of seals. -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug, Display, From)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = dbc::LIB_NAME_BPCORE, tags = custom)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase", untagged) -)] -pub enum TxPtr { - /// Points to the witness transaction of some other closed seal. - #[default] - #[display("~")] - #[strict_type(tag = 0x0)] - WitnessTx, - - /// Points to a transaction by the transaction id. - #[from] - #[display(inner)] - #[strict_type(tag = 0x1)] - Txid(Txid), -} - -impl From<&Txid> for TxPtr { - #[inline] - fn from(txid: &Txid) -> Self { TxPtr::Txid(*txid) } -} - -impl From<[u8; 32]> for TxPtr { - #[inline] - fn from(txid: [u8; 32]) -> Self { TxPtr::Txid(txid.into()) } -} - -impl SealTxid for TxPtr { - fn txid(&self) -> Option { - match self { - TxPtr::WitnessTx => None, - TxPtr::Txid(txid) => Some(*txid), - } - } - - fn txid_or(&self, default: Txid) -> Txid { - match self { - TxPtr::WitnessTx => default, - TxPtr::Txid(txid) => *txid, - } - } - - fn map_to_outpoint(&self, vout: impl Into) -> Option { - self.txid().map(|txid| Outpoint::new(txid, vout)) - } -} - -impl FromStr for TxPtr { - type Err = hex::Error; - - fn from_str(s: &str) -> Result { - match s { - "~" => Ok(TxPtr::WitnessTx), - other => Txid::from_str(other).map(Self::from), - } - } -} diff --git a/seals/src/txout/witness.rs b/seals/src/txout/witness.rs deleted file mode 100644 index fa66b458..00000000 --- a/seals/src/txout/witness.rs +++ /dev/null @@ -1,99 +0,0 @@ -// Bitcoin protocol single-use-seals library. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use bc::{Tx, Txid}; -use commit_verify::mpc; -use single_use_seals::SealWitness; - -use crate::txout::{TxoSeal, VerifyError}; - -/// Witness of a bitcoin-based seal being closed. Includes both transaction and -/// extra-transaction data. -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -pub struct Witness { - /// Witness transaction: transaction which contains commitment to the - /// message over which the seal is closed. - pub tx: Tx, - - /// Transaction id of the witness transaction above. - pub txid: Txid, - - /// Deterministic bitcoin commitment proof from the anchor. - pub proof: D, -} - -impl Witness { - /// Constructs witness from a witness transaction and extra-transaction - /// proof, taken from an anchor. - pub fn with(tx: Tx, dbc: D) -> Witness { - Witness { - txid: tx.txid(), - tx, - proof: dbc, - } - } -} - -impl SealWitness for Witness { - type Message = mpc::Commitment; - type Error = VerifyError; - - fn verify_seal(&self, seal: &Seal, msg: &Self::Message) -> Result<(), Self::Error> { - // 1. The seal must match tx inputs - let outpoint = seal.outpoint().ok_or(VerifyError::NoWitnessTxid)?; - if !self.tx.inputs.iter().any(|txin| txin.prev_output == outpoint) { - return Err(VerifyError::WitnessNotClosingSeal(outpoint)); - } - - // 2. Verify DBC with the giving closing method - self.proof.verify(msg, &self.tx).map_err(VerifyError::Dbc) - } - - fn verify_many_seals<'seal>( - &self, - seals: impl IntoIterator, - msg: &Self::Message, - ) -> Result<(), Self::Error> - where - Seal: 'seal, - { - let mut method = None; - for seal in seals { - // 1. All seals must have the same closing method - if let Some(method) = method { - if method != seal.method() { - return Err(VerifyError::InconsistentCloseMethod); - } - } else { - method = Some(seal.method()); - } - - // 2. Each seal must match tx inputs - let outpoint = seal.outpoint().ok_or(VerifyError::NoWitnessTxid)?; - if !self.tx.inputs.iter().any(|txin| txin.prev_output == outpoint) { - return Err(VerifyError::WitnessNotClosingSeal(outpoint)); - } - } - - // 3. Verify DBC with the giving closing method - self.proof.verify(msg, &self.tx).map_err(VerifyError::Dbc) - } -} diff --git a/src/bin/bpcore-stl.rs b/src/bin/bpcore-stl.rs index e9f41d57..38b39328 100644 --- a/src/bin/bpcore-stl.rs +++ b/src/bin/bpcore-stl.rs @@ -26,7 +26,8 @@ use bc::stl::{bp_consensus_stl, bp_tx_stl}; use bp::stl::bp_core_stl; use commit_verify::stl::commit_verify_stl; use commit_verify::CommitmentLayout; -use seals::txout::{ChainBlindSeal, SingleBlindSeal}; +use dbc::tapret::TapretProof; +use seals::TxoSeal; use strict_encoding::libname; use strict_types::stl::std_stl; use strict_types::{parse_args, SystemBuilder}; @@ -113,13 +114,11 @@ Seals vesper lexicon=types+commitments " ) .unwrap(); - let layout = SingleBlindSeal::commitment_layout(); + let layout = TxoSeal::::commitment_layout(); writeln!(file, "{layout}").unwrap(); - let layout = ChainBlindSeal::commitment_layout(); - writeln!(file, "{layout}").unwrap(); - let tt = sys.type_tree("BPCore.BlindSealTxid").unwrap(); + let tt = sys.type_tree("BPCore.TxoSealTapretProof").unwrap(); writeln!(file, "{tt}").unwrap(); - let tt = sys.type_tree("BPCore.BlindSealTxPtr").unwrap(); + let tt = sys.type_tree("BPCore.TxoSealOpretProof").unwrap(); writeln!(file, "{tt}").unwrap(); let tt = sys.type_tree("BPCore.AnchorMerkleTreeTapretProof").unwrap(); diff --git a/src/stl.rs b/src/stl.rs index 31722998..e690b303 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -21,18 +21,16 @@ //! Strict types library generator methods. -use bc::Txid; use commit_verify::mpc; use dbc::opret::OpretProof; use dbc::tapret::TapretProof; use dbc::LIB_NAME_BPCORE; -use seals::txout::TxPtr; use strict_types::{CompileError, LibBuilder, TypeLib}; /// Strict types id for the library providing data types from [`dbc`] and /// [`seals`] crates. pub const LIB_ID_BPCORE: &str = - "stl:VhPW19SH-c5lzr1y-TLIsx8z-Z5nB!$Q-IgwrAQA-OqXLwUg#austin-story-retro"; + "stl:A3Hq5xgH-a7u2hJJ-XyPrSVp-~bVLnkf-A1KMLfv-MeK4lEw#russian-granite-campus"; fn _bp_core_stl() -> Result { LibBuilder::new(libname!(LIB_NAME_BPCORE), tiny_bset! { @@ -46,11 +44,11 @@ fn _bp_core_stl() -> Result { .transpile::>() .transpile::>() .transpile::>() - .transpile::>() - .transpile::>() + .transpile::>() + .transpile::>() + .transpile::>() + .transpile::>() .transpile::() - .transpile::>() - .transpile::>() .compile() } diff --git a/stl/Anchor.MerkleBlock.Tapret.vesper b/stl/Anchor.MerkleBlock.Tapret.vesper index 9eb0988a..3a17016d 100644 --- a/stl/Anchor.MerkleBlock.Tapret.vesper +++ b/stl/Anchor.MerkleBlock.Tapret.vesper @@ -1,30 +1,31 @@ -AnchorMerkleBlockTapretProof rec - mpcProof rec MerkleBlock - depth enum { - U5 _0=0 _1=1 _2=2 _3=3 _4=4 _5=5 _6=6 _7=7 - _8=8 _9=9 _10=10 _11=11 _12=12 _13=13 _14=14 _15=15 - _16=16 _17=17 _18=18 _19=19 _20=20 _21=21 _22=22 _23=23 - _24=24 _25=25 _26=26 _27=27 _28=28 _29=29 _30=30 _31=31 +rec AnchorMerkleBlockTapretProof + rec mpcProof, MerkleBlock + enum method, Method, sha256t 0 + enum depth { + U5, _0 0, _1 1, _2 2, _3 3, _4 4, _5 5, _6 6, _7 7 + _8 8, _9 9, _10 10, _11 11, _12 12, _13 13, _14 14, _15 15 + _16 16, _17 17, _18 18, _19 19, _20 20, _21 21, _22 22, _23 23 + _24 24, _25 25, _26 26, _27 27, _28 28, _29 29, _30 30, _31 31 } - cofactor is U16 - crossSection list len=1..MAX32 - TreeNode union - concealedNode rec tag=0 - depth enum { - U5 _0=0 _1=1 _2=2 _3=3 _4=4 _5=5 _6=6 _7=7 - _8=8 _9=9 _10=10 _11=11 _12=12 _13=13 _14=14 _15=15 - _16=16 _17=17 _18=18 _19=19 _20=20 _21=21 _22=22 _23=23 - _24=24 _25=25 _26=26 _27=27 _28=28 _29=29 _30=30 _31=31 + is cofactor, U16 + list crossSection, len 1..MAX32 + union TreeNode + rec concealedNode, tag 0 + enum depth { + U5, _0 0, _1 1, _2 2, _3 3, _4 4, _5 5, _6 6, _7 7 + _8 8, _9 9, _10 10, _11 11, _12 12, _13 13, _14 14, _15 15 + _16 16, _17 17, _18 18, _19 19, _20 20, _21 21, _22 22, _23 23 + _24 24, _25 25, _26 26, _27 27, _28 28, _29 29, _30 30, _31 31 } - hash bytes len=32 aka=MerkleHash - commitmentLeaf rec tag=1 - protocolId bytes len=32 aka=ProtocolId - message bytes len=32 aka=Message - some is U64 option wrapped tag=1 - dbcProof rec TapretProof - pathProof rec TapretPathProof - some union TapretNodePartner option wrapped tag=1 - rightBranch rec TapretRightBranch wrapped tag=2 - nonce is U8 + bytes hash, len 32, aka MerkleHash + rec commitmentLeaf, tag 1 + bytes protocolId, len 32, aka ProtocolId + bytes message, len 32, aka Message + is some, U64, option, wrapped, tag 1 + rec dbcProof, TapretProof + rec pathProof, TapretPathProof + union some, TapretNodePartner, option, wrapped, tag 1 + rec rightBranch, TapretRightBranch, wrapped, tag 2 + is nonce, U8 diff --git a/stl/Anchor.MerkleProof.Tapret.vesper b/stl/Anchor.MerkleProof.Tapret.vesper index dd18c240..d84300b0 100644 --- a/stl/Anchor.MerkleProof.Tapret.vesper +++ b/stl/Anchor.MerkleProof.Tapret.vesper @@ -1,11 +1,12 @@ -AnchorMerkleProofTapretProof rec - mpcProof rec MerkleProof - pos is U32 - cofactor is U16 - path list len=0..32 - element bytes len=32 aka=MerkleHash - dbcProof rec TapretProof - pathProof rec TapretPathProof - some union TapretNodePartner option wrapped tag=1 - rightBranch rec TapretRightBranch wrapped tag=2 - nonce is U8 +rec AnchorMerkleProofTapretProof + rec mpcProof, MerkleProof + enum method, Method, sha256t 0 + is pos, U32 + is cofactor, U16 + list path, len 0..32 + bytes element, len 32, aka MerkleHash + rec dbcProof, TapretProof + rec pathProof, TapretPathProof + union some, TapretNodePartner, option, wrapped, tag 1 + rec rightBranch, TapretRightBranch, wrapped, tag 2 + is nonce, U8 diff --git a/stl/Anchor.MerkleTree.Opret.vesper b/stl/Anchor.MerkleTree.Opret.vesper index dbcb800b..0e9f561a 100644 --- a/stl/Anchor.MerkleTree.Opret.vesper +++ b/stl/Anchor.MerkleTree.Opret.vesper @@ -1,20 +1,21 @@ -AnchorMerkleTreeOpretProof rec - mpcProof rec MerkleTree - depth enum { - U5 _0=0 _1=1 _2=2 _3=3 _4=4 _5=5 _6=6 _7=7 - _8=8 _9=9 _10=10 _11=11 _12=12 _13=13 _14=14 _15=15 - _16=16 _17=17 _18=18 _19=19 _20=20 _21=21 _22=22 _23=23 - _24=24 _25=25 _26=26 _27=27 _28=28 _29=29 _30=30 _31=31 +rec AnchorMerkleTreeOpretProof + rec mpcProof, MerkleTree + enum method, Method, sha256t 0 + enum depth { + U5, _0 0, _1 1, _2 2, _3 3, _4 4, _5 5, _6 6, _7 7 + _8 8, _9 9, _10 10, _11 11, _12 12, _13 13, _14 14, _15 15 + _16 16, _17 17, _18 18, _19 19, _20 20, _21 21, _22 22, _23 23 + _24 24, _25 25, _26 26, _27 27, _28 28, _29 29, _30 30, _31 31 } - entropy is U64 - cofactor is U16 - messages map len=0..MAX24 - key bytes len=32 aka=ProtocolId - value bytes len=32 aka=Message - map map len=0..MAX24 - key is U32 - value tuple - _ bytes len=32 aka=ProtocolId - _ bytes len=32 aka=Message - dbcProof is Unit aka=OpretProof + is entropy, U64 + is cofactor, U16 + map messages, len 0..MAX24 + bytes key, len 32, aka ProtocolId + bytes value, len 32, aka Message + map map, len 0..MAX24 + is key, U32 + tuple value + bytes _, len 32, aka ProtocolId + bytes _, len 32, aka Message + is dbcProof, Unit, aka OpretProof diff --git a/stl/Anchor.MerkleTree.Tapret.vesper b/stl/Anchor.MerkleTree.Tapret.vesper index e61fb2fe..650077cd 100644 --- a/stl/Anchor.MerkleTree.Tapret.vesper +++ b/stl/Anchor.MerkleTree.Tapret.vesper @@ -1,24 +1,25 @@ -AnchorMerkleTreeTapretProof rec - mpcProof rec MerkleTree - depth enum { - U5 _0=0 _1=1 _2=2 _3=3 _4=4 _5=5 _6=6 _7=7 - _8=8 _9=9 _10=10 _11=11 _12=12 _13=13 _14=14 _15=15 - _16=16 _17=17 _18=18 _19=19 _20=20 _21=21 _22=22 _23=23 - _24=24 _25=25 _26=26 _27=27 _28=28 _29=29 _30=30 _31=31 +rec AnchorMerkleTreeTapretProof + rec mpcProof, MerkleTree + enum method, Method, sha256t 0 + enum depth { + U5, _0 0, _1 1, _2 2, _3 3, _4 4, _5 5, _6 6, _7 7 + _8 8, _9 9, _10 10, _11 11, _12 12, _13 13, _14 14, _15 15 + _16 16, _17 17, _18 18, _19 19, _20 20, _21 21, _22 22, _23 23 + _24 24, _25 25, _26 26, _27 27, _28 28, _29 29, _30 30, _31 31 } - entropy is U64 - cofactor is U16 - messages map len=0..MAX24 - key bytes len=32 aka=ProtocolId - value bytes len=32 aka=Message - map map len=0..MAX24 - key is U32 - value tuple - _ bytes len=32 aka=ProtocolId - _ bytes len=32 aka=Message - dbcProof rec TapretProof - pathProof rec TapretPathProof - some union TapretNodePartner option wrapped tag=1 - rightBranch rec TapretRightBranch wrapped tag=2 - nonce is U8 + is entropy, U64 + is cofactor, U16 + map messages, len 0..MAX24 + bytes key, len 32, aka ProtocolId + bytes value, len 32, aka Message + map map, len 0..MAX24 + is key, U32 + tuple value + bytes _, len 32, aka ProtocolId + bytes _, len 32, aka Message + rec dbcProof, TapretProof + rec pathProof, TapretPathProof + union some, TapretNodePartner, option, wrapped, tag 1 + rec rightBranch, TapretRightBranch, wrapped, tag 2 + is nonce, U8 diff --git a/stl/BPCore@0.1.0.sta b/stl/BPCore@0.1.0.sta index 490973c9..a9fbacbe 100644 --- a/stl/BPCore@0.1.0.sta +++ b/stl/BPCore@0.1.0.sta @@ -1,63 +1,65 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:VhPW19SH-c5lzr1y-TLIsx8z-Z5nB!$Q-IgwrAQA-OqXLwUg#austin-story-retro +Id: stl:A3Hq5xgH-a7u2hJJ-XyPrSVp-~bVLnkf-A1KMLfv-MeK4lEw#russian-granite-campus Name: BPCore Dependencies: - CommitVerify#miller-pancake-elastic, + CommitVerify#escort-between-doctor, Std#ralph-blue-lucky, Bitcoin#signal-color-cipher -Check-SHA256: ffe8ef061b2a6733287e1874f8781a637640f3c99f05eb07d25c3a0aa5ed269e +Check-SHA256: e1b9b1eb5098fceaff315d7f8f4afb99a33e803f79cb247ee601220ceaa12a25 -20~CnZ*pY=dIKHbX?@G`sCP;~6&DQwR5(-fxrUo0Th4E?M+l67UG^w8*<_XZ#%uyqCj(P-Wc6$lVk7oBr%DNv+($;q`HHK!gIHa)*%m(-e#9sm3I{@IbYpL6 -ZUYBGX>?<6X>JGrA>%$n#j0HLDJN5-IKgM_J7b(p+0MPGk2Gl)y2(Rz1Xgc#bS10xxe^o?x}!PNUwajG +ZUYBGX>?<6X>JJsA>%$n#j0HLDJN5-IKgM_J7b(p+0MPGk2Gl)y2(Rz1Xgc#bS10xxe^o?x}!PNUwajG r*TW+dUY6G&@nZ7)X6RBh6__;a%pgMLV0v$b1}QF=!A)P#jpo4axu-4_As_7EzOC4+`8Vyy2R;!*$Y%* a87SzWk_LjXkV<^ZRI~s#T41Gjc0(`3ajfaCJX&HEu+ACq+L0mO$tn9VP;cfa%pgMqk=;7%h%D+p%U7S ;b1RT)c9`>#Kd;Rz-U=aO9W+B1XOrwWT}OOcT=8d`>?<6$C@F;S3|*6`1-v+nBdcqJ?FPKcnV2wbY*gG -VQf%qwlfK-7{9iX4Q|L-q$GzUMp|h#f#{Gz8SzLEaTf~c{WkYggkPIjuQ -HS#3Ua|L6d7%qre2Ut&TYsZfv!yd427@;7veO2zMB=| -GYU;*a%*g5NMUnmT+QYFd;Umr-dgNEFCuu*?Wk)@WS(Jw`th(K{eY_63r%HmYiwmgY;R+0h0#5^R?l+2 ->x*OcO&#*^E;5@PQ20HKbE5LJk_Il(3r%HmYiwmua&K>D*tNNq^HspzKK^|l-Ci`?%`u0U6ZHVlY`S(f -i`CFq2vl-qWlnEoWdl=mWB~wXSa8^mT+s=T=}Z?`J=~w8Q=GLzSfImTncuED0}GM@RW%X-8$oVkXm4^& -WpZn5WkPIkV{1=va%FT-a&K>D1_B6eaAQz%Z*OJ-dIKHbX?@G`sCP;~6&DQwR5(-fxrUo0Th0tjtzV^DH$Z)O5|10COKearHwcS=7M -7YzYaI8*bvhMOc?)(rkC#nUES&E@`k{z!7(TI@Y9B6!g4sB24Po?(Fc@vtHNfU4XGWMX4ba&K>D0S~qx -m_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s3>!giV`y)3O=WUxY-Lb#Z*OK#aB^jIP;zf?W(EQXZE#~y -a&K>D0(t`--)Viz@~C%8KNS}Z0aQ3s^SOqbBwN-D{wl@OCWX;GxmM3|zUzx)^-Ue}@Gdf&9Z>i^jdP;% -w2}rc(FkN>V^DH$Z)O2UPS0G>=uAF%>iaxCSnRl2&38AmXJiCw9urENI6IddL2hGcZ*om#a%*g5P;zf? -W>jHta%FT-a&K>D1_B6eaAQz%Z*OJ-dIKHbX?@G`sCP;~6&DQwR5(-fxrUo0Thx*OcO&#*^E;5@PQ20HKbE5LJk_Il(2xMYoP;zf?W&sbjADBNH?W>M^%H|xc>sh|Dn*!v8^Ea7rh?dzC -2n-rQZewU~a!qA&Yiwmya%E*taB^jIP;zf?W(EQXZE#~ya&K>D0(t`--)Viz@~C%8KNS}Z0aQ3s^SOqb -BwN-D{wl@OCJ0vde;(yN=uAF%>iaxC -SnRl2&38AmXJiCw9urENI6IdcL2hGcZ*om#a%*g5RB~lyRAF#(Wpq$-Z*OJ>0tjtzV^DH$Z)O5|10COK -earHwcS=7M7YzYaI8*bvhMOc?)(rkC#nUDTR`-7%D0S~qxm_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s3=TqUX>MdwWnpYocu;h51_TCeWprq7WC1R> -5GA>8Wft0d6dj=*oo`t>c$)o5X19O9`rXu=lIsL?cxhw-vE?{96bd-L@NXK=z8qksZ{gweeRv2cdB4&6 -(-0xu1a@zAbOQBk6JjIwIj2eqliWu}$@z+_xPw?-wb>Rw7=FYk8VVufK10Q-T=FR=Q=>S+XYD&Ml#00<32Y-w&}Q)OXnRCsA*1_TCeWprq7WC1R>5GA>8Wft0d6dj=*oo`t> -c$)o5X19O9`rXu=lIsL?cxhw;^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jHqk=;7%h%D+p%U7S -;b1RT)c9`>#Kd;Rz-U=aO9W+B1a@zAbOQBk6JjIwIj2eqliWu}$@z+_xPw?-wb>Rw7=FYk8VVufK10Q- -T=FR=Q=>S+XYD&Ml#005GA>8Wft0d6dj=*oo`t>c$)o5X19O9`rXu=lIsL?cxhw-vE?{96bd-L@NXK=z8qksZ{gweeRv2c -dB4&6(-0xu1a@zAbOQBk6JjIwIj2eqliWu}$@z+_xPw?-wb>Rw7=FYk8VVufK10Q-T=FR=Q=>S+XYD&< -oK4xzy{V5hX&1W5Lv;{EcyMfKV`+3#WnpYocxhw?0|sqnbZBp60WP-?CAn^87TS9h9ibhaZ&^Bcn*B*; -w|~I;-PD|t>jZRoX=DQRY!hN5_Bp3Y36tDMM#=e#tGI($UA5U3KNx<*C>jc*fi7rMzqbp}mkbZBp60|E+faB^jIMrm?$bN~xM0`+VY -Vk7oBr%DNv+($;q`HHK!gIHa)*%m(-e#9sm3NgE`=!A)P#jpo4axu-4_As_7EzOC4+`8Vyy2R;!*#QZ1 -X=iA3Ol4ta00jX8^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jHU#!_}M0RemmT>wB!7L}MA7sFvK -#<=RP4S#T1Vv-hhTICs&5e05N37a&BR4P-_D9Y!hN5_Bp3Y36tDMM#=e#tGI($UA5U3KNx<*C>jc> -g@kugo@o29zwXDHA;ech!BqJAy+4@X(~&*rw>NkZRAF#(Wpq+$XJ~Xna$#;`Xa)idY-MJ2PH$voNMUnm -0`+VYVk7oBr%DNv+($;q`HHK!gIHa)*%m(-e#9sm3NgE`=!A)P#jpo4axu-4_As_7EzOC4+`8Vyy2R;! -*$r}OXJ~XzZ)9aiVRL8#^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jHF}tqlgo$^>um>@6G0l?p -Ft#Zz&53{9y57aQ#OZ(81yp!YbaDg&010<#bZ%vHb5wW$00035ba-iG00jX8^=uPjBlbC`N(qzPM@Gr{ -imSMTSY5T*7C#t%#3&jHqk=;7%h%D+p%U7S;b1RT)c9`>#Kd;Rz-U=aO9W+B +VQf%qwlfK-7{9iX4Q|L-q$GzUMp|h#f#=xRXCTqXIv;)MTcr4cfxK`S9u +y$)6q!N22#m0-mN2v2o%aBpdDbo`>HD!!5a&4Q@0n2=*4!cKOosx|T?(Q^f3pcpQQSqE58Zfto_YYang +ZEb0ER%LQ&W_bw!17eyujlDm-l!bcJ4l3enMo5^RQ~n#iGkyWd8~8$g22EvjXm4aLDsvRr2gft{Sr^|c +6mQ&%Z&uBrV^&@~cF6SzV@1=_p5>Oab-~jCR3C`SFec^=zG+gvC{`lWpi_3XJt5^Lxv|61vo|c_Jr^I{59gDgg^Q~>5XMaf24xdt)Bj2hqB2&USqe>Ma%*g5RB~lyllNeFa6}P}rq7L! +(40)FbL%msz%JU8hqvFyoea2o4pL=vWpZ|9WI}m#WpgpuwYiq_Rlwao{(T?aUNqayF^88E^#IUpx^^~; +)zDW6RB~lyPH$vo15y0X3z7m=H4*?DL2hGcZ*om# +a%*g5LTqniYfo@;Wpq$-Z*OJ>0tjtzV^DH$Z)O6wTyVnzGkys4bL0OiA1G+LtF{%ZG2CjE*m|hC5a9VP +DsvRr2gft{Sr^|c6mQ&%Z&uBrV^&@~cF6SzD0Y^^HT+rxDK6vW;JU&?LxLM72H?wDC +1Zo}=N}D)4mmEQEV`y)3O=WUxY-K`hZ)0mzVQ_L~bWn0{Z)OGp2yJjD1_B6eaAQz% +Z*OJ-w_I?;0yBOH^mF6?Djz6lx~sMot1;YamDqZyx)9*`N|BtQMKZZ6divcSvT6VUPd7++HJ~!1&&J-V +2cFWC2xMYoP;zf?W&uY|&s@;xOg?z(`#e5a?6_IYcQ>D +RAF#(Wpq$-Z*OJ>0tjtzV^DH$Z)O6wTyVnzGkys4bL0OiA1G+LtF{%ZG2CjE*m|hC5a9Vrk({ALGPx>x +`rRI~Y5)OGH%NCipfaP+#@?w1p3;*DWMX4ba&K>D0S~qxm_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s +3>rahV`y)3O=WUxY-Ln(Wo1ura%FT-a&K>D1_B6eaAQz%Z*OJ-w_I?;0yBOH^mF6?Djz6lx~sMot1;Ya +mDqZyx)9*`bJO-c7a!dZ=aZj>i>o;h#!UqVWfNo5|4I#_GFF{g2xMYoP;zf?W&uY|&s@;xOg?z(`#e5a +?6_IYcQ>D +0=Han!vZsY2=sH~|0*9SXu7Mm6{|7aYL(b}sJal~`AU(Tp+z#eDth|e9=uAF%>iaxCSnRl2&38AmXJiCw9urENI6IdOW?^h>Vqs%zP;zf?W&*cdaKi#K +ehBn)D1_KCfaAQz%Z*OJ-w_I?;0yBOH^mF6?Djz6lx~sMot1;YamDqZyx)9*`N|BtQMKZZ6 +divcSvT6VUPd7++HJ~!1&&J-V2cFWC2xMYoP;zf?W&sbjADBNH?W>M^%H|xc>sh|Dn*!v8^Ea7rh?dzC +2n-EoVQg$-VPk7ha&K>D0=Han!vZsY2=sH~|0*9SXu7Mm6{|7aYL(b}sJal~`IGlxcyL4!ji%3ykI(--0RRU806;_l3QuryWpq$-Z*OJ=0RR913R7ica%FT=WnpXu0RRU8 +06-uB5maGta%FT*Z)9aqVRCeCWpV@q00?YlW^_((WMu#a0Rr`G6JjIwIj2eqliWu}$@z+_xPw?-wb>Rw +7=FYk8VWJHuIPk`cg3&=F>*1@lJ+pRDJ{*3f84s>#k$1lf7t;Ea%pF1bWCMoW&i~N0`+VYVk7oBr%DNv ++($;q`HHK!gIHa)*%m(-e#9sm3SX?*ZRI~s#T41Gjc0(`3ajfaCJX&HEu+ACq+L0mO#%yYX=iA3LULhl +V`u;c0RcEaVlHu0(#Ro^Jj-_-pFL#XcJe4ySuOZRLzEUxZ3PchVQ_L~bWmY*Xi#!*Z)OGp3vgj_bZ%vG +PH$vo00aU61a5C`WdHyG0R(ezZDjxj0RaJg2VDR_OBR)w8yCZ2EylR&t_^>1Sz?kFbz0>alMw}OZ*F5{ +0003CRAF#(Wpq$-Z*OJ>0ts+obZAg=Z*OJ+6U0+eW+%HuC5$^~^vuG3{`}-8x6fV={eh1!etXz_3TbY1 +WpZv|Y*1?g^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jHsfC1hQ=Vx1u)prdnjyqjL%~$|`n^Ax +;M0*k=eIX_5maGta%FTRw7=FYk8VWJHuIPk`cg3&=F>*1@lJ+pRDJ{*3f84s>#k$1lf7uOkX=iA3PH$voNMUnm0`+VYVk7oB +r%DNv+($;q`HHK!gIHa)*%m(-e#9sm3NgE`=!A)P#jpo4axu-4_As_7EzOC4+`8Vyy2R;!*$Py6Z&PJq +Y(;o<1OfmBZf|LGWdH>M0q^-VhdM_j&Xz2y10MAh|FpnPu}M=HJieTRp&m;}YXJymVQg$-VPk6m1pxx} +Y!hN5_Bp3Y36tDMM#=e#tGI($UA5U3KNx<*C>jdrYCz3gCHcMLg#T%!5i+MiDY62ZUYgq2{$1_^UzV{dL`VRCr^H*7+z;q=?lBqOBSI9H7B +1B!$rGO>p)(#S64kD@pX -----END STRICT TYPE LIB----- diff --git a/stl/BPCore@0.1.0.stl b/stl/BPCore@0.1.0.stl index b3ed8f82..a47cb11f 100644 Binary files a/stl/BPCore@0.1.0.stl and b/stl/BPCore@0.1.0.stl differ diff --git a/stl/BPCore@0.1.0.sty b/stl/BPCore@0.1.0.sty index 08188457..7bde4b63 100644 --- a/stl/BPCore@0.1.0.sty +++ b/stl/BPCore@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:VhPW19SH-c5lzr1y-TLIsx8z-Z5nB!$Q-IgwrAQA-OqXLwUg#austin-story-retro + Id: stl:A3Hq5xgH-a7u2hJJ-XyPrSVp-~bVLnkf-A1KMLfv-MeK4lEw#russian-granite-campus Name: BPCore Version: 0.1.0 Description: Bitcoin client-side-validation library @@ -11,13 +11,15 @@ @context typelib BPCore -import CommitVerify#miller-pancake-elastic - use MerkleTree#patriot-answer-oliver +import CommitVerify#escort-between-doctor + use Method#subject-justin-cowboy + use MerkleBlock#america-reptile-aloha use ProtocolId#shadow-eclipse-program use Message#druid-blitz-rover use MerkleHash#horse-popcorn-bundle - use MerkleBlock#pegasus-delta-eddie - use MerkleProof#price-aloha-grid + use MerkleProof#austria-jaguar-donald + use MerkleTree#anita-castle-herbert + use ReservedBytes1#origin-roger-relax use TreeNode#kansas-scarlet-ricardo import Std#ralph-blue-lucky @@ -31,52 +33,40 @@ import Bitcoin#signal-color-cipher use Txid#shallow-light-reverse use InternalPk#habitat-paprika-oliver use LeafVer#benefit-carbon-africa + use Outpoint#logo-alamo-madam use XOnlyPk#clever-swim-carpet -@mnemonic(bread-poncho-pattern) +@mnemonic(pattern-pierre-galileo) data AnchorMerkleBlockOpretProof : mpcProof CommitVerify.MerkleBlock, dbcProof OpretProof -@mnemonic(madrid-vampire-little) +@mnemonic(match-forget-expand) data AnchorMerkleBlockTapretProof : mpcProof CommitVerify.MerkleBlock, dbcProof TapretProof -@mnemonic(almond-gilbert-urban) +@mnemonic(road-simon-animal) data AnchorMerkleProofOpretProof : mpcProof CommitVerify.MerkleProof, dbcProof OpretProof -@mnemonic(llama-colony-juice) +@mnemonic(genesis-cinema-fame) data AnchorMerkleProofTapretProof : mpcProof CommitVerify.MerkleProof, dbcProof TapretProof -@mnemonic(season-perform-tropic) +@mnemonic(poker-segment-spoon) data AnchorMerkleTreeOpretProof : mpcProof CommitVerify.MerkleTree, dbcProof OpretProof -@mnemonic(europe-mister-imitate) +@mnemonic(tokyo-yankee-garcia) data AnchorMerkleTreeTapretProof : mpcProof CommitVerify.MerkleTree, dbcProof TapretProof -@mnemonic(report-process-stuart) -data BlindSealTxPtr : method Method - , txid TxPtr - , vout Bitcoin.Vout - , blinding U64 +@mnemonic(disney-apropos-costume) +data AnchorOpretProof : mpcProof CommitVerify.MerkleProof + , dbcProof OpretProof + , fallbackProof CommitVerify.ReservedBytes1 -@mnemonic(baby-region-proxy) -data BlindSealTxid : method Method - , txid Bitcoin.Txid - , vout Bitcoin.Vout - , blinding U64 - -@mnemonic(meaning-extra-sherman) -data ExplicitSealTxPtr : method Method - , txid TxPtr - , vout Bitcoin.Vout - -@mnemonic(june-total-denver) -data ExplicitSealTxid : method Method - , txid Bitcoin.Txid - , vout Bitcoin.Vout - -@mnemonic(bali-boris-plasma) -data Method : opretFirst | tapretFirst +@mnemonic(speech-jerome-phoenix) +data AnchorTapretProof : mpcProof CommitVerify.MerkleProof + , dbcProof TapretProof + , fallbackProof CommitVerify.ReservedBytes1 +@mnemonic(basket-match-colony) +data Noise : [Byte ^ 68] @mnemonic(good-village-flex) data OpretProof : () @@ -98,8 +88,14 @@ data TapretProof : pathProof TapretPathProof, internalPk Bitcoin.InternalP @mnemonic(miracle-patriot-touch) data TapretRightBranch : leftNodeHash Bitcoin.TapNodeHash, rightNodeHash Bitcoin.TapNodeHash -@mnemonic(italian-july-eddie) -data TxPtr : witnessTx () - | txid Bitcoin.Txid +@mnemonic(stamp-morning-tulip) +data TxoSealExt : noise Noise + | fallback Bitcoin.Outpoint + +@mnemonic(igloo-viva-orient) +data TxoSealOpretProof : primary Bitcoin.Outpoint, secondary TxoSealExt + +@mnemonic(hobby-yogurt-taboo) +data TxoSealTapretProof : primary Bitcoin.Outpoint, secondary TxoSealExt diff --git a/stl/Bitcoin@0.1.0.sta b/stl/Bitcoin@0.1.0.sta index f4224576..d45b071f 100644 --- a/stl/Bitcoin@0.1.0.sta +++ b/stl/Bitcoin@0.1.0.sta @@ -1,5 +1,5 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:q7G95wzt-SxT2BMV-t!PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda +Id: stl:q7G95wzt-SxT2BMV-t~PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda Name: Bitcoin Dependencies: Std#ralph-blue-lucky Check-SHA256: a62302ba13b4099c7b6868061d1891d66d81e220fd8530082ee47dedccde7053 diff --git a/stl/Bitcoin@0.1.0.sty b/stl/Bitcoin@0.1.0.sty index 3a142dde..6d64784f 100644 --- a/stl/Bitcoin@0.1.0.sty +++ b/stl/Bitcoin@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:q7G95wzt-SxT2BMV-t!PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda + Id: stl:q7G95wzt-SxT2BMV-t~PokBt-wNYgZTu-AaYAtM3-rYjlzs4#agenda-wolf-pagoda Name: Bitcoin Version: 0.1.0 Description: Consensus library for bitcoin protocol diff --git a/stl/Seals.vesper b/stl/Seals.vesper index f212aaef..2b400304 100644 --- a/stl/Seals.vesper +++ b/stl/Seals.vesper @@ -7,23 +7,26 @@ Seals vesper lexicon=types+commitments -SecretSeal commitment hasher=SHA256 tagged=urn:lnp-bp:seals:secret#2024-02-03 - BlindSealTxid serialized +commitment SecretSeal, hasher SHA256, tagged urn:lnp-bp:seals:secret#2024-02-03 + serialized TxoSealTapretProof -SecretSeal commitment hasher=SHA256 tagged=urn:lnp-bp:seals:secret#2024-02-03 - BlindSealTxPtr serialized +rec TxoSealTapretProof + rec primary, Outpoint + bytes txid, len 32, aka Txid + is vout, U32, aka Vout + union secondary, TxoSealExt + bytes noise, len 68, wrapped, aka Noise, tag 0 + rec fallback, Outpoint, wrapped, tag 1 + bytes txid, len 32, aka Txid + is vout, U32, aka Vout -BlindSealTxid rec - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - -BlindSealTxPtr rec - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 +rec TxoSealOpretProof + rec primary, Outpoint + bytes txid, len 32, aka Txid + is vout, U32, aka Vout + union secondary, TxoSealExt + bytes noise, len 68, wrapped, aka Noise, tag 0 + rec fallback, Outpoint, wrapped, tag 1 + bytes txid, len 32, aka Txid + is vout, U32, aka Vout