diff --git a/Cargo.lock b/Cargo.lock index cac330b..ff04f9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,6 +108,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bp" +version = "0.11.0" +dependencies = [ + "amplify", + "bp-invoice", + "bp-std", + "psbt", +] + +[[package]] +name = "bp-invoice" +version = "0.11.0" +dependencies = [ + "amplify", + "bp-std", + "serde", +] + [[package]] name = "bp-primitives" version = "0.10.6" @@ -121,7 +140,7 @@ dependencies = [ ] [[package]] -name = "bp-wallet" +name = "bp-std" version = "0.11.0" dependencies = [ "amplify", @@ -280,6 +299,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psbt" +version = "0.11.0" +dependencies = [ + "amplify", + "bp-std", + "serde", +] + [[package]] name = "quote" version = "1.0.32" diff --git a/Cargo.toml b/Cargo.toml index 301e17f..59c11f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ -[package] -name = "bp-wallet" +[workspace] +members = ["std", "invoice", "psbt", "."] + +[workspace.package] version = "0.11.0" -description = "Modern, minimalistic & standard-compliant cold wallet library" keywords = ["bitcoin", "wallet", "descriptor-wallet", "psbt", "taproot"] categories = ["cryptography::cryptocurrencies"] -readme = "README.md" authors = ["Dr Maxim Orlovsky "] homepage = "https://lnp-bp.org" repository = "https://github.com/BP-WG/bp-wallet" @@ -12,20 +12,40 @@ rust-version = "1.60" # Due to rust-amplify edition = "2021" license = "Apache-2.0" -[lib] -name = "bp" - -[dependencies] +[workspace.dependencies] amplify = "4.0.0" bitcoin_hashes = "0.12.0" bech32 = "0.9.1" bp-primitives = "0.10.6" -serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } +serde_crate = { package = "serde", version = "1", features = ["derive"] } + +[package] +name = "bp-wallet" +version = { workspace = true } +description = "Modern, minimalistic & standard-compliant cold wallet library" +keywords = { workspace = true } +categories = { workspace = true } +readme = "README.md" +authors = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } + +[lib] +name = "bp" + +[dependencies] +amplify = { workspace = true } +bp-std = { path = "std" } +bp-invoice = { path = "invoice" } +psbt = { path = "psbt" } [features] default = [] all = ["serde"] -serde = ["serde_crate", "bp-primitives/serde"] +serde = ["amplify/serde", "bp-std/serde", "bp-invoice/serde", "psbt/serde"] [patch.crates-io] bp-primitives = { git = "https://github.com/BP-WG/bp-core", branch = "primitives" } diff --git a/MANIFEST.yml b/MANIFEST.yml index 4f6363f..2c4433a 100644 --- a/MANIFEST.yml +++ b/MANIFEST.yml @@ -1,4 +1,4 @@ -Name: bp-bips +Name: bp-wallet Type: Library Kind: Free software License: Apache-2.0 diff --git a/convert/Cargo.lock b/convert/Cargo.lock deleted file mode 100644 index b98a9a3..0000000 --- a/convert/Cargo.lock +++ /dev/null @@ -1,419 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "amplify" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26966af46e0d200e8bf2b7f16230997c1c3f2d141bc27ccc091c012ed527b58" -dependencies = [ - "amplify_apfloat", - "amplify_derive", - "amplify_num", - "amplify_syn", - "ascii", - "wasm-bindgen", -] - -[[package]] -name = "amplify_apfloat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5b7f29fad2a3def5dfbfed0da85b886eb927a18fe0296c06e39880b7a96db05" -dependencies = [ - "amplify_num", - "bitflags", -] - -[[package]] -name = "amplify_derive" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87df0f28e6eb1f2d355f29ba6793fa9ca643967528609608d5cbd70bd68f9d1" -dependencies = [ - "amplify_syn", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "amplify_num" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddce3bc63e807ea02065e8d8b702695f3d302ae4158baddff8b0ce5c73947251" - -[[package]] -name = "amplify_syn" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7736fb8d473c0d83098b5bac44df6a561e20470375cd8bcae30516dc889fd62a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ascii" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" - -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "bitcoin" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" -dependencies = [ - "bech32", - "bitcoin-private", - "bitcoin_hashes", - "hex_lit", - "secp256k1", -] - -[[package]] -name = "bitcoin-private" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" - -[[package]] -name = "bitcoin_hashes" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" -dependencies = [ - "bitcoin-private", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bp-convert" -version = "0.11.0" -dependencies = [ - "amplify", - "bitcoin", - "bp-wallet", - "secp256k1", -] - -[[package]] -name = "bp-primitives" -version = "0.10.6" -source = "git+https://github.com/BP-WG/bp-core?branch=primitives#76959e5f9198c9d6e5bfe129ba3ab8fe3c84b64e" -dependencies = [ - "amplify", - "commit_verify", - "secp256k1", - "strict_encoding", -] - -[[package]] -name = "bp-wallet" -version = "0.11.0" -dependencies = [ - "amplify", - "bech32", - "bitcoin_hashes", - "bp-primitives", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "commit_encoding_derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00033f14d67c4169d588f085ea2faeb7b610cf03a74d42ea09eeba31abef2047" -dependencies = [ - "amplify", - "amplify_syn", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "commit_verify" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa8114b3ff20947176c8cbfd1e84e56649501eed4e33ba9205c70374b2615ae" -dependencies = [ - "amplify", - "commit_encoding_derive", - "sha2", - "strict_encoding", -] - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hex_lit" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "log" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "secp256k1" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" -dependencies = [ - "bitcoin_hashes", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" -dependencies = [ - "cc", -] - -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "strict_encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b1c91b79e62afc09025d828fa0b8dbf4105513de38f126a017919c09bca472" -dependencies = [ - "amplify", - "strict_encoding_derive", -] - -[[package]] -name = "strict_encoding_derive" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5adae55367464f5a229bfd539682c94f870b98a220be6e61dc43f85d612e7e" -dependencies = [ - "amplify_syn", - "heck", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.27", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.27", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" diff --git a/convert/Cargo.toml b/convert/Cargo.toml deleted file mode 100644 index bb37c99..0000000 --- a/convert/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "bp-convert" -version = "0.11.0" -description = "Convertor between bp-wallet and rust-bitcoin data types" -keywords = ["bitcoin", "wallet"] -categories = ["cryptography::cryptocurrencies"] -readme = "README.md" -authors = ["Dr Maxim Orlovsky "] -homepage = "https://lnp-bp.org" -repository = "https://github.com/BP-WG/bp-wallet" -rust-version = "1.60" # Due to rust-amplify -edition = "2021" -license = "Apache-2.0" - -[lib] -name = "bconv" - -[dependencies] -amplify = "4.0.0" -secp256k1 = "0.27.0" -bitcoin = "0.30.1" -bp-wallet = { path = ".." } - -[patch.crates-io] -bp-primitives = { git = "https://github.com/BP-WG/bp-core", branch = "primitives" } diff --git a/esplora b/esplora deleted file mode 160000 index e040e30..0000000 --- a/esplora +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e040e30b755dc81bd4d7b5294a8b0c6406bfc95f diff --git a/invoice/Cargo.toml b/invoice/Cargo.toml new file mode 100644 index 0000000..7146c4b --- /dev/null +++ b/invoice/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "bp-invoice" +version = { workspace = true } +description = "Invoces with Bitcoin protocol" +keywords = { workspace = true } +categories = { workspace = true } +readme = "../README.md" +authors = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } + +[dependencies] +amplify = { workspace = true } +bp-std = { path = "../std" } +serde_crate = { workspace = true, optional = true } + +[features] +default = [] +all = ["serde"] +serde = ["serde_crate", "bp-std/serde"] diff --git a/convert/src/lib.rs b/invoice/src/lib.rs similarity index 61% rename from convert/src/lib.rs rename to invoice/src/lib.rs index 454a03c..fa51f7a 100644 --- a/convert/src/lib.rs +++ b/invoice/src/lib.rs @@ -1,4 +1,4 @@ -// Convertor between bp-wallet and rust-bitcoin data types. +// Modern, minimalistic & standard-compliant cold wallet library. // // SPDX-License-Identifier: Apache-2.0 // @@ -19,21 +19,3 @@ // 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 amplify::RawArray; -use bitcoin::hashes::Hash; - -pub trait Convertible { - type Target: Sized; - fn convert(&self) -> Self::Target; -} - -impl Convertible for bp::Txid { - type Target = bitcoin::Txid; - fn convert(&self) -> Self::Target { Self::Target::from_byte_array(self.to_raw_array()) } -} - -impl Convertible for bitcoin::Txid { - type Target = bp::Txid; - fn convert(&self) -> Self::Target { Self::Target::from_raw_array(self.to_byte_array()) } -} diff --git a/legacy/anchor.rs b/legacy/anchor.rs deleted file mode 100644 index 5aaa1e0..0000000 --- a/legacy/anchor.rs +++ /dev/null @@ -1,122 +0,0 @@ -#[cfg(feature = "wallet")] -/// Errors working with anchors. -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)] -#[display(inner)] -pub enum Error { - /// Errors embedding LNPBP-4 commitment into PSBT - #[from] - EmbedCommit(PsbtCommitError), - - /// Errors constructing LNPBP-4 commitment - #[from] - Lnpbp4(lnpbp4::Error), -} - -impl Anchor { - /// Returns id of the anchor (commitment hash). - #[inline] - pub fn anchor_id(&self) -> AnchorId { self.consensus_commit() } - - /// Convenience constructor for anchor, which also does embedding of LNPBP4 - /// commitment into PSBT. - #[cfg(feature = "wallet")] - pub fn commit( - psbt: &mut Psbt, - ) -> Result, Error> { - let anchor = psbt.embed_commit(&PsbtEmbeddedMessage)?; - Ok(Anchor { - txid: anchor.txid, - lnpbp4_proof: lnpbp4::MerkleBlock::from(anchor.lnpbp4_proof), - dbc_proof: anchor.dbc_proof, - }) - } -} - -#[cfg(feature = "wallet")] -impl EmbedCommitProof -for Anchor -{ - fn restore_original_container( - &self, - psbt: &Psbt, - ) -> Result { - match self.dbc_proof { - Proof::OpretFirst => Ok(psbt.clone()), - Proof::TapretFirst(ref proof) => { - let mut psbt = psbt.clone(); - for output in &mut psbt.outputs { - if output.is_tapret_host() { - *output = EmbedCommitProof::<_, psbt::Output, Lnpbp6>::restore_original_container(proof, output)?; - return Ok(psbt); - } - } - Err(PsbtVerifyError::Commit( - PsbtCommitError::CommitmentImpossible, - )) - } - } - } -} - -#[cfg(feature = "wallet")] -impl EmbedCommitVerify for Psbt { - type Proof = Anchor; - type CommitError = PsbtCommitError; - type VerifyError = PsbtVerifyError; - - fn embed_commit( - &mut self, - _: &PsbtEmbeddedMessage, - ) -> Result { - let lnpbp4_tree = - |output: &mut psbt::Output| -> Result<_, PsbtCommitError> { - let messages = output.lnpbp4_message_map()?; - let min_depth = output - .lnpbp4_min_tree_depth()? - .unwrap_or(ANCHOR_MIN_LNPBP4_DEPTH); - let multi_source = lnpbp4::MultiSource { - min_depth, - messages, - }; - Ok(lnpbp4::MerkleTree::try_commit(&multi_source)?) - }; - - let (dbc_proof, lnpbp4_proof) = if let Some(output) = - self.outputs.iter_mut().find(|o| o.is_tapret_host()) - { - let tree = lnpbp4_tree(output)?; - let commitment = tree.consensus_commit(); - let proof = output.embed_commit(&commitment)?; - output.set_tapret_commitment(commitment.into_array(), &proof)?; - output.set_lnpbp4_entropy(tree.entropy())?; - (Proof::TapretFirst(proof), tree) - } else if let Some(output) = - self.outputs.iter_mut().find(|o| o.is_opret_host()) - { - let tree = lnpbp4_tree(output)?; - let commitment = tree.consensus_commit(); - output.script = Script::new_op_return(commitment.as_slice()).into(); - output.set_opret_commitment(commitment.into_array())?; - output.set_lnpbp4_entropy(tree.entropy())?; - (Proof::OpretFirst, tree) - } else { - return Err(PsbtCommitError::CommitmentImpossible); - }; - - Ok(Anchor { - txid: self.to_txid(), - lnpbp4_proof, - dbc_proof, - }) - } -} - - -/// Empty type indicating that the message has to be taken from PSBT proprietary -/// keys -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct PsbtEmbeddedMessage; - -impl CommitEncode for PsbtEmbeddedMessage { - fn commit_encode(&self, _: E) -> usize { 0 } -} diff --git a/legacy/psbtout.rs b/legacy/psbtout.rs deleted file mode 100644 index b8f4d40..0000000 --- a/legacy/psbtout.rs +++ /dev/null @@ -1,178 +0,0 @@ -// Deterministic bitcoin commitments library, implementing LNPBP standards -// Part of bitcoin protocol core library (BP Core Lib) -// -// Written in 2020-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the Apache 2.0 License -// along with this software. -// If not, see . - -use bitcoin::hashes::Hash; -use bitcoin::psbt::TapTree; -use bitcoin::util::taproot::TapBranchHash; -use bitcoin::Script; -use bitcoin_scripts::taproot::{Node, TaprootScriptTree, TreeNode}; -use bitcoin_scripts::TapNodeHash; -use commit_verify::convolve_commit::ConvolveCommitVerify; -use commit_verify::{lnpbp4, EmbedCommitProof, EmbedCommitVerify}; -use psbt::commit::{ - DfsPathEncodeError, Lnpbp4KeyError, OpretKeyError, TapretKeyError, -}; -use secp256k1::SECP256K1; - -use super::{Lnpbp6, TapretProof}; -use crate::tapret::taptree::{ - TapretProofError, TapretSourceError, TapretSourceInfo, -}; - -/// Errors during tapret PSBT commitment process. -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum PsbtCommitError { - /// Invalid taproot script tree source information. - #[from] - #[display(inner)] - SourceError(TapretSourceError), - - /// it is impossible to create neither Tapret nor Opret commitment for the - /// given PSBT file. - CommitmentImpossible, - - /// Error in LNPBP4 PBST data - #[from] - #[display(inner)] - PsbtLnpbp4(Lnpbp4KeyError), - - /// Error in LNPBP4 PBST data - #[from] - #[display(inner)] - TapretLnpbp4(TapretKeyError), - - /// Error in LNPBP4 PBST data - #[from] - #[display(inner)] - OpretLnpbp4(OpretKeyError), - - /// LNPBP4 commitment creation error - #[from] - #[display(inner)] - Lnpbp4(lnpbp4::Error), - - /// tapret commitment can't be made in a transaction lacking any taproot - /// outputs. - NoTaprootOutput, - - /// tapret commitment can't be made due to an absent taproot internal key - /// in PSBT data. - InternalKeyMissed, - - /// tapret commitment does not change internal key, but the key in PSBT - /// data and key from the tapret proof differ. - InternalKeyMismatch, - - /// invalid tapret commitment path in PSBT data. - #[from(DfsPathEncodeError)] - TapretPathInvalid, - - /// PSBT output misses tapret path information. - TapretPathMissed, - - /// producing taptree structure - TapTreeError, -} - -/// Errors during tapret PSBT commitment process. -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)] -#[display(inner)] -pub enum PsbtVerifyError { - /// Error during commitment process. - #[from] - #[from(DfsPathEncodeError)] - #[from(TapretSourceError)] - Commit(PsbtCommitError), - - /// Error during verification process. - #[from] - Proof(TapretProofError), -} - -impl EmbedCommitProof - for TapretProof -{ - fn restore_original_container( - &self, - commit_container: &psbt::Output, - ) -> Result { - let mut original_container = commit_container.clone(); - - let internal_key = original_container - .tap_internal_key - .ok_or(PsbtCommitError::InternalKeyMissed)?; - if internal_key != self.internal_key { - return Err(PsbtCommitError::InternalKeyMismatch) - .map_err(PsbtVerifyError::from); - } - - let tap_tree = original_container.tap_tree.map(TaprootScriptTree::from); - let source = TapretSourceInfo::::with(tap_tree)?; - let source = self.path_proof.restore_original_container(&source)?; - - let merkle_root = source - .as_root_node() - .map(TreeNode::node_hash) - .map(TapNodeHash::into_inner) - .map(TapBranchHash::from_inner); - original_container.script = - Script::new_v1_p2tr(SECP256K1, self.internal_key, merkle_root) - .into(); - - original_container.tap_tree = source.into_tap_tree(); - - Ok(original_container) - } -} - -impl EmbedCommitVerify for psbt::Output { - type Proof = TapretProof; - type CommitError = PsbtCommitError; - type VerifyError = PsbtVerifyError; - - fn embed_commit( - &mut self, - msg: &lnpbp4::CommitmentHash, - ) -> Result { - // TODO: Check TAPRET_COMMITABLE key - - let internal_key = if let Some(internal_key) = self.tap_internal_key { - internal_key - } else { - return Err(PsbtCommitError::InternalKeyMissed); - }; - - let mut source = - TapretSourceInfo::::with(self.tap_tree.clone())?; - - let path_proof = source.embed_commit(msg)?; - - self.tap_tree = source.into_tap_tree(); - - let (output_key, _) = internal_key - .convolve_commit(&path_proof, msg) - .map_err(|_| PsbtCommitError::TapTreeError)?; - - self.script = Script::new_v1_p2tr_tweaked(output_key).into(); - - let proof = TapretProof { - path_proof, - internal_key, - }; - - Ok(proof) - } -} diff --git a/legacy/scripts.rs b/legacy/scripts.rs deleted file mode 100644 index 9ab07b8..0000000 --- a/legacy/scripts.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::util::Bytes; - -/// Bare script is a bitcoin script which may be present in a pre-segwit -/// contexts, i.e. in bare, P2PK & P2PKH `scriptPubkeys`, pre-segwit -/// `redeemScript` and in only pre-BIP16 `sigScript` (pre-segwit `sigScripts` -/// spending P2SH outputs do not contain this script type and use -/// [`Bip16SigScript`] instead). -/// -/// The structure doesn't put any assumptions regarding consensus script -/// limitations, including (but not limiting to) validity of public keys or -/// signatures present in the script, correctness of the script business logic, -/// minimal and maximal length of the script etc. -/// -/// Bare script is any sequence of bytes and may be parsed into pre-taproot -/// op codes using some softfork context. However, the parsing may fail, and -/// the failed parsing must not indicate that the transaction is invalid; as -/// well as the ability to parse a bare script into opcodes does not indicate -/// validity of the transaction. -#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug, From)] -#[wrapper(RangeOps, BorrowSlice, Hex)] -#[wrapper_mut(RangeMut, BorrowSliceMut)] -pub struct BareScript(#[from] #[from(&[u8])] #[from(Vec)]Bytes); - -/// Redeem script is a script which is deserialized from the last data push -/// in BIP-16 compliant transactions. -pub struct RedeemScript(BareScript); - -pub struct Bip16SigScript { - pub sigs: Vec>, - pub redeemScript: RedeemScript -} - -pub struct TapScript(Bytes); - -pub enum ScriptPubkey { - Bare(BareScript), - Witness { - version: WitnessVer, - program: WitnessProg, - }, -} - -/// A content of the script from `witness` structure; en equivalent of -/// `redeemScript` for witness-based transaction inputs. However, unlike -/// [`RedeemScript`], [`WitnessScript`] produce SHA256-based hashes of -/// [`WScriptHash`] type - and it is prohibited to contain uncompressed keys. -/// -/// Witness script can be nested within the redeem script in legacy -/// P2WSH-in-P2SH schemes; for this purpose use [`RedeemScript::from`] method. -pub struct WitnessScript(BareScript); - -pub enum LeafScript { - TapScript(TapScript), - Future { - version: FutureLeafVer, - script: Box<[u8]>, - }, -} - -pub enum SigScript { - Bare(BareScript), - Bip16(Bip16Script), - - SegwitEmpty, -} diff --git a/legacy/serialize.rs b/legacy/serialize.rs deleted file mode 100644 index a78fb93..0000000 --- a/legacy/serialize.rs +++ /dev/null @@ -1,181 +0,0 @@ -// BP Core Library implementing LNP/BP specifications & standards related to -// bitcoin protocol -// -// Written in 2020-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the Apache 2.0 License -// along with this software. -// If not, see . - -use std::io::{self, Read, Write}; - -use super::ScriptBytes; -use crate::LeafScript; - -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] -#[display("end of data reached while parsing with bitcoin consensus rules")] -pub struct NoData; - -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] -#[display("serialization overflow")] -pub struct TooLarge; - -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum DataError { - #[from(NoData)] - /// end of data reached while parsing with bitcoin consensus rules - NoData, - - /// data left after complete deserialization of bitcoin structure - ExcessiveData, -} - -pub trait ConsensusRead: Read { - fn read_u8(&mut self) -> Result; - fn read_u16(&mut self) -> Result; - fn read_u32(&mut self) -> Result; - fn read_u64(&mut self) -> Result; - fn read_var_int(&mut self) -> Result; -} - -pub trait ConsensusWrite: Write { - fn write_u8(&mut self, val: u8) -> Result<(), io::Error>; - fn write_u16(&mut self, val: u16) -> Result<(), io::Error>; - fn write_u32(&mut self, val: u32) -> Result<(), io::Error>; - fn write_u64(&mut self, val: u64) -> Result<(), io::Error>; - fn write_var_int(&mut self, val: u64) -> Result<(), io::Error>; -} - -/// Consensus data can't be larger than 4000000 -pub type ConsensusIo = ConfinedIo; - -impl ConsensusRead for R { - fn read_u8(&mut self) -> Result { - let mut val = [0; 1]; - self.read_exact(&mut val)?; - Ok(val[0]) - } - fn read_u16(&mut self) -> Result { - let mut val = [0; 2]; - self.read_exact(&mut val)?; - Ok(u16::from_le_bytes(val)) - } - fn read_u32(&mut self) -> Result { - let mut val = [0; 4]; - self.read_exact(&mut val)?; - Ok(u32::from_le_bytes(val)) - } - fn read_u64(&mut self) -> Result { - let mut val = [0; 8]; - self.read_exact(&mut val)?; - Ok(u64::from_le_bytes(val)) - } - - fn read_var_int(&mut self) -> Result { - let n = self.read_u8()?; - match n { - 0xFF => { - let x = self.read_u64()?; - if x < 0x100000000 { - Err(io::ErrorKind::InvalidInput.into()) - } else { - Ok(x) - } - } - 0xFE => { - let x = self.read_u32()?; - if x < 0x10000 { - Err(io::ErrorKind::InvalidInput.into()) - } else { - Ok(x as u64) - } - } - 0xFD => { - let x = self.read_u16()?; - if x < 0xFD { - Err(io::ErrorKind::InvalidInput.into()) - } else { - Ok(x as u64) - } - } - n => Ok(n as u64), - } - } -} - -impl ConsensusWrite for W { - fn write_u8(&mut self, val: u8) -> Result<(), io::Error> { - self.write_all(&[val]) - } - - fn write_u16(&mut self, val: u16) -> Result<(), io::Error> { - self.write_all(&val.to_le_bytes()) - } - - fn write_u32(&mut self, val: u32) -> Result<(), io::Error> { - self.write_all(&val.to_le_bytes()) - } - - fn write_u64(&mut self, val: u64) -> Result<(), io::Error> { - self.write_all(&val.to_le_bytes()) - } - - fn write_var_int(&mut self, val: u64) -> Result<(), io::Error> { - match val { - 0..=0xFC => { - self.write_u8(val as u8)?; - } - 0xFD..=0xFFFF => { - self.write_u8(0xFD)?; - self.write_u16(val as u16)?; - } - 0x10000..=0xFFFFFFFF => { - self.write_u8(0xFE)?; - self.write_u32(val as u32)?; - } - _ => { - self.write_u8(0xFF)?; - self.write_u64(val as u64)?; - } - } - Ok(()) - } -} - -pub trait ConsensusDecode: Sized { - fn consensus_decode(reader: impl ConsensusRead) -> Result; -} - -pub trait ConsensusEncode { - fn consensus_encode( - &self, - writer: impl ConsensusWrite, - ) -> Result<(), io::Error>; -} - -impl ConsensusEncode for ScriptBytes { - fn consensus_encode( - &self, - mut writer: impl ConsensusWrite, - ) -> Result<(), io::Error> { - writer.write_var_int(self.len() as u64)?; - writer.write_all(self.as_ref()) - } -} - -impl ConsensusEncode for LeafScript { - fn consensus_encode( - &self, - mut writer: impl ConsensusWrite, - ) -> Result<(), io::Error> { - writer.write_u8(self.version.to_consensus())?; - self.script.consensus_encode(writer) - } -} diff --git a/legacy/short_id.rs b/legacy/short_id.rs deleted file mode 100644 index fa9c699..0000000 --- a/legacy/short_id.rs +++ /dev/null @@ -1,677 +0,0 @@ -// BP Core Library implementing LNP/BP specifications & standards related to -// bitcoin protocol -// -// Written in 2020-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the Apache 2.0 License -// along with this software. -// If not, see . - -use std::convert::{TryFrom, TryInto}; -use std::fmt::Debug; - -use bitcoin::{BlockHash, Txid}; - -#[derive(Copy, Clone, Debug, Display, PartialEq, Eq)] -#[display(doc_comments)] -/// Errors from descriptor validation and parsing -pub enum Error { - /// invalid block height - BlockHeightOutOfRange, - /// invalid tx input index - InputIndexOutOfRange, - /// invalid tx output index - OutputIndexOutOfRange, - /// invalid tx checksum - ChecksumOutOfRange, - /// tx dimension not defined - DimensionRequired, - /// descriptor upgrade - UpgradeImpossible, - /// descriptor downgrade - DowngradeImpossible, -} - -/// Checksum for block id data used by the LNPBP-5 -#[derive( - Wrapper, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, - Display, From -)] -#[display("{0}", alt = "block_checksum:{0:#}")] -#[wrapper(FromStr, LowerHex, UpperHex, Octal)] -pub struct BlockChecksum(u8); - -impl From for BlockChecksum { - fn from(block_hash: BlockHash) -> Self { - let mut xor: u8 = 0; - for byte in &block_hash[..] { - xor ^= byte; - } - Self::from(xor) - } -} - -/// Checksum for transaction id data used by the LNPBP-5 -#[derive( - Wrapper, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, - Display, From -)] -#[display("{0}", alt = "tx_checksum:{0:#}")] -#[wrapper(FromStr, LowerHex, UpperHex, Octal)] -pub struct TxChecksum(u64); - -impl From for TxChecksum { - fn from(txid: Txid) -> Self { - let mut checksum: u64 = 0; - for (shift, byte) in txid.to_vec()[0..5].iter().enumerate() { - checksum ^= (*byte as u64) << (shift * 8); - } - Self::from(checksum) - } -} - -/// Descriptor enum defines the onchain/offchain entity type -#[derive(Copy, Clone, Debug)] -pub enum Descriptor { - /// Block included onchain - OnchainBlock { - /// Height of onchain block - block_height: u32, - /// Checksum of onchain block - block_checksum: BlockChecksum, - }, - /// Tx included onchain - OnchainTransaction { - /// Height of the block tx belongs to - block_height: u32, - /// Checksum of the block tx belongs to - block_checksum: BlockChecksum, - /// Index in the block tx belongs to - tx_index: u16, - }, - /// Tx input included onchain - OnchainTxInput { - /// Height of the block the tx input belongs to - block_height: u32, - /// Checksum of the block the tx input belongs to - block_checksum: BlockChecksum, - /// Index in the block tx belongs to - tx_index: u16, - /// Index in the tx the input belongs to - input_index: u16, - }, - /// Tx output included onchain - OnchainTxOutput { - /// Height of the block the tx input belongs to - block_height: u32, - /// Checksum of the block the tx input belongs to - block_checksum: BlockChecksum, - /// Index in the block tx belongs to - tx_index: u16, - /// Index in the tx the output belongs to - output_index: u16, - }, - /// Tx not included onchain - OffchainTransaction { - /// Offchain tx checksum - tx_checksum: TxChecksum, - }, - /// Tx input not included onchain - OffchainTxInput { - /// Offchain tx checksum - tx_checksum: TxChecksum, - /// Index in the tx the input belongs to - input_index: u16, - }, - /// Tx output not included onchain - OffchainTxOutput { - /// Offchain tx checksum - tx_checksum: TxChecksum, - /// Index in the tx the output belongs to - output_index: u16, - }, -} - -/// Dimension enum defines tx dimension scope in terms of input/output relation -#[derive(Copy, Clone, Debug, Display, PartialEq, Eq)] -pub enum Dimension { - /// Tx input - #[display("input")] - Input, - /// Tx output - #[display("output")] - Output, -} - -impl Default for Descriptor { - fn default() -> Self { - Descriptor::OnchainBlock { - block_height: 0, - block_checksum: BlockChecksum::default(), - } - } -} - -impl Descriptor { - /// Verifies if Descriptor type has valid properties otherwise returns - /// validation error - pub fn try_validity(&self) -> Result<(), Error> { - match *self { - Descriptor::OnchainTransaction { block_height, .. } - | Descriptor::OnchainTxInput { block_height, .. } - | Descriptor::OnchainTxOutput { block_height, .. } - if block_height >= (2u32 << 22) => - { - Err(Error::BlockHeightOutOfRange) - } - Descriptor::OnchainTxInput { input_index, .. } - | Descriptor::OffchainTxInput { input_index, .. } - if input_index + 1 >= (2u16 << 14) => - { - Err(Error::InputIndexOutOfRange) - } - Descriptor::OnchainTxOutput { output_index, .. } - | Descriptor::OffchainTxOutput { output_index, .. } - if output_index + 1 >= (2u16 << 14) => - { - Err(Error::OutputIndexOutOfRange) - } - Descriptor::OffchainTransaction { tx_checksum, .. } - | Descriptor::OffchainTxInput { tx_checksum, .. } - | Descriptor::OffchainTxOutput { tx_checksum, .. } - if *tx_checksum >= (2u64 << 46) => - { - Err(Error::ChecksumOutOfRange) - } - _ => Ok(()), - } - } - - /// Returns true if Descriptor type is either OnchainBlock or - /// OnchainTransaction or OnchainTxInput or OnchainTxOutput - pub fn is_onchain(&self) -> bool { - matches!( - self, - Descriptor::OnchainBlock { .. } - | Descriptor::OnchainTransaction { .. } - | Descriptor::OnchainTxInput { .. } - | Descriptor::OnchainTxOutput { .. } - ) - } - - /// Returns true if Descriptor type is not onchain type - pub fn is_offchain(&self) -> bool { !self.is_onchain() } - - /// Upgraded returns the "wrapped descriptor" based on provided parameters. - /// for instance, tx is returned in case descriptor is a block, as well as - /// input/out is returned in case descriptor is a tx and dimension is - /// specified - pub fn upgraded( - &self, - index: u16, - dimension: Option, - ) -> Result { - use Dimension::*; - - match (*self, dimension) { - ( - Descriptor::OnchainBlock { - block_height, - block_checksum, - }, - None, - ) => Ok(Descriptor::OnchainTransaction { - block_height, - block_checksum, - tx_index: index, - }), - ( - Descriptor::OnchainTransaction { - block_height, - block_checksum, - tx_index, - }, - Some(dim), - ) if dim == Input => Ok(Descriptor::OnchainTxInput { - block_height, - block_checksum, - tx_index, - input_index: index, - }), - ( - Descriptor::OnchainTransaction { - block_height, - block_checksum, - tx_index, - }, - Some(dim), - ) if dim == Output => Ok(Descriptor::OnchainTxOutput { - block_height, - block_checksum, - tx_index, - output_index: index, - }), - (Descriptor::OffchainTransaction { tx_checksum }, Some(dim)) - if dim == Input => - { - Ok(Descriptor::OffchainTxInput { - tx_checksum, - input_index: index, - }) - } - (Descriptor::OffchainTransaction { tx_checksum }, Some(dim)) - if dim == Output => - { - Ok(Descriptor::OffchainTxOutput { - tx_checksum, - output_index: index, - }) - } - (Descriptor::OnchainTransaction { .. }, None) - | (Descriptor::OffchainTransaction { .. }, None) => { - Err(Error::DimensionRequired) - } - _ => Err(Error::UpgradeImpossible), - } - } - - /// Downgraded returns the "wrapper descriptor", i.e. in case the descriptor - /// is an onchain tx, the onchain block is returned, as well as the onchain - /// tx is returned for onchain input/output - pub fn downgraded(self) -> Result { - match self { - Descriptor::OnchainTransaction { - block_height, - block_checksum, - .. - } => Ok(Descriptor::OnchainBlock { - block_height, - block_checksum, - }), - Descriptor::OnchainTxInput { - block_height, - block_checksum, - tx_index, - .. - } - | Descriptor::OnchainTxOutput { - block_height, - block_checksum, - tx_index, - .. - } => Ok(Descriptor::OnchainTransaction { - block_height, - block_checksum, - tx_index, - }), - Descriptor::OffchainTxInput { tx_checksum, .. } - | Descriptor::OffchainTxOutput { tx_checksum, .. } => { - Ok(Descriptor::OffchainTransaction { tx_checksum }) - } - _ => Err(Error::DowngradeImpossible), - } - } - - /// Get block height extracting from Descriptor - pub fn get_block_height(&self) -> Option { - match self { - Descriptor::OnchainBlock { block_height, .. } - | Descriptor::OnchainTransaction { block_height, .. } - | Descriptor::OnchainTxInput { block_height, .. } - | Descriptor::OnchainTxOutput { block_height, .. } => { - Some(*block_height) - } - _ => None, - } - } - - /// Get block checksum extracting from Descriptor - pub fn get_block_checksum(&self) -> Option { - match self { - Descriptor::OnchainBlock { block_checksum, .. } - | Descriptor::OnchainTransaction { block_checksum, .. } - | Descriptor::OnchainTxInput { block_checksum, .. } - | Descriptor::OnchainTxOutput { block_checksum, .. } => { - Some(**block_checksum) - } - _ => None, - } - } - - /// Get tx checksum extracting from Descriptor - pub fn get_tx_checksum(&self) -> Option { - match self { - Descriptor::OffchainTransaction { tx_checksum, .. } - | Descriptor::OffchainTxInput { tx_checksum, .. } - | Descriptor::OffchainTxOutput { tx_checksum, .. } => { - Some(**tx_checksum) - } - _ => None, - } - } - - /// Get tx index extracting from Descriptor - pub fn get_tx_index(&self) -> Option { - match self { - Descriptor::OnchainTransaction { tx_index, .. } - | Descriptor::OnchainTxInput { tx_index, .. } - | Descriptor::OnchainTxOutput { tx_index, .. } => Some(*tx_index), - _ => None, - } - } - - /// Get input index extracting from Descriptor - pub fn get_input_index(&self) -> Option { - match self { - Descriptor::OnchainTxInput { input_index, .. } - | Descriptor::OffchainTxInput { input_index, .. } => { - Some(*input_index) - } - _ => None, - } - } - - /// Get output index extracting from Descriptor - pub fn get_output_index(&self) -> Option { - match self { - Descriptor::OnchainTxOutput { output_index, .. } - | Descriptor::OffchainTxOutput { output_index, .. } => { - Some(*output_index) - } - _ => None, - } - } - - /// Tries to convert short id from Descriptor to u64 - pub fn try_into_u64(self) -> Result { - ShortId::try_from(self).map(ShortId::into_u64) - } -} - -/// Short id is a descriptor representation that allows to build a Descriptor -/// starting from a specific mask -#[derive( - Copy, - Clone, - PartialOrd, - Ord, - PartialEq, - Eq, - Hash, - Debug, - Display, - StrictEncode, - StrictDecode -)] -#[display("{0:016X}")] -pub struct ShortId(u64); - -impl ShortId { - /// Specifies offchain descriptor - pub const FLAG_OFFCHAIN: u64 = 0x8000_0000_0000_0000; - /// Specifies block descriptor and allows block height definition - pub const MASK_BLOCK: u64 = 0x7FFF_FF00_0000_0000; - /// Allows block checksum definition - pub const MASK_BLOCKCHECK: u64 = 0x0000_00FF_0000_0000; - /// Allows tx index definition - pub const MASK_TXIDX: u64 = 0x0000_0000_FFFF_0000; - /// Allows tx checksum definition - pub const MASK_TXCHECK: u64 = 0x7FFF_FFFF_FFFF_0000; - /// Specifies tx input or output descriptor - pub const FLAG_INOUT: u64 = 0x0000_0000_0000_8000; - /// Allows tx index definition and specifies tx descriptor - pub const MASK_INOUT: u64 = 0x0000_0000_0000_7FFF; - - /// Operation for block height definition - pub const SHIFT_BLOCK: u64 = 40; - /// Operation for block checksum definition - pub const SHIFT_BLOCKCHECK: u64 = 32; - /// Operation for tx id and tx checksum definition - pub const SHIFT_TXIDX: u64 = 16; - - /// Returns if onchain descriptor is represented - pub fn is_onchain(&self) -> bool { - self.0 & Self::FLAG_OFFCHAIN != Self::FLAG_OFFCHAIN - } - /// Returns if offchain descriptor is represented - pub fn is_offchain(&self) -> bool { - self.0 & Self::FLAG_OFFCHAIN == Self::FLAG_OFFCHAIN - } - - /// Generates descriptor from short id definition - pub fn get_descriptor(&self) -> Descriptor { - #[inline] - fn iconv(val: u64) -> T - where - T: TryFrom, - >::Error: Debug, - { - val.try_into() - .expect("Conversion from existing ShortId can't fail") - } - - let index: u16 = iconv(self.0 & Self::MASK_INOUT); - - if self.is_onchain() { - let block_height: u32 = - iconv((self.0 & Self::MASK_BLOCK) >> Self::SHIFT_BLOCK); - let block_checksum = BlockChecksum::from(iconv::( - (self.0 & Self::MASK_BLOCKCHECK) >> Self::SHIFT_BLOCKCHECK, - )); - if (self.0 & (!Self::MASK_BLOCK)) == 0 { - return Descriptor::OnchainBlock { - block_height, - block_checksum, - }; - } - let tx_index: u16 = - iconv((self.0 & Self::MASK_TXIDX) >> Self::SHIFT_TXIDX); - if (self.0 & (!Self::MASK_INOUT)) == 0 { - return Descriptor::OnchainTransaction { - block_height, - block_checksum, - tx_index, - }; - } - if (self.0 & Self::FLAG_INOUT) == 0 { - Descriptor::OnchainTxInput { - block_height, - block_checksum, - tx_index, - input_index: index - 1, - } - } else { - Descriptor::OnchainTxOutput { - block_height, - block_checksum, - tx_index, - output_index: index - 1, - } - } - } else { - let tx_checksum = TxChecksum::from( - (self.0 & Self::MASK_TXCHECK) >> Self::SHIFT_TXIDX, - ); - if (self.0 & (!Self::MASK_INOUT)) == 0 { - return Descriptor::OffchainTransaction { tx_checksum }; - } - if (self.0 & Self::FLAG_INOUT) == 0 { - Descriptor::OffchainTxInput { - tx_checksum, - input_index: index - 1, - } - } else { - Descriptor::OffchainTxOutput { - tx_checksum, - output_index: index - 1, - } - } - } - } - - /// Converts short id into inner u64 - pub fn into_u64(self) -> u64 { self.into() } -} - -impl From for Descriptor { - fn from(short_id: ShortId) -> Self { short_id.get_descriptor() } -} - -impl TryFrom for ShortId { - type Error = self::Error; - - fn try_from(descriptor: Descriptor) -> Result { - use Descriptor::*; - - descriptor.try_validity()?; - - let block_height: u64 = match descriptor { - OnchainBlock { block_height, .. } - | OnchainTransaction { block_height, .. } - | OnchainTxInput { block_height, .. } - | OnchainTxOutput { block_height, .. } => block_height, - _ => 0, - } as u64; - let block_checksum = *match descriptor { - OnchainBlock { block_checksum, .. } - | OnchainTransaction { block_checksum, .. } - | OnchainTxInput { block_checksum, .. } - | OnchainTxOutput { block_checksum, .. } => block_checksum, - _ => BlockChecksum::default(), - } as u64; - let tx_index = match descriptor { - OnchainTransaction { tx_index, .. } - | OnchainTxInput { tx_index, .. } - | OnchainTxOutput { tx_index, .. } => tx_index, - _ => 0, - } as u64; - let tx_checksum = match descriptor { - OffchainTransaction { tx_checksum } - | OffchainTxInput { tx_checksum, .. } - | OffchainTxOutput { tx_checksum, .. } => tx_checksum, - _ => TxChecksum::default(), - }; - let inout_index: u64 = match descriptor { - OnchainTxInput { input_index, .. } - | OffchainTxInput { input_index, .. } => input_index + 1, - OnchainTxOutput { output_index, .. } - | OffchainTxOutput { output_index, .. } => output_index + 1, - _ => 0, - } as u64; - - let mut short_id = 0u64; - short_id |= inout_index; - if descriptor.is_offchain() { - short_id |= Self::FLAG_OFFCHAIN; - short_id |= - (*tx_checksum << Self::SHIFT_TXIDX) & Self::MASK_TXCHECK; - } else { - short_id |= (block_height << 40) & Self::MASK_BLOCK; - short_id |= (block_checksum << Self::SHIFT_BLOCKCHECK) - & Self::MASK_BLOCKCHECK; - short_id |= (tx_index << 16) & Self::MASK_TXIDX; - } - - match descriptor { - OnchainTxOutput { .. } | OffchainTxOutput { .. } => { - short_id |= Self::FLAG_INOUT << Self::SHIFT_TXIDX - } - _ => (), - } - - Ok(Self(short_id)) - } -} - -impl From for ShortId { - fn from(val: u64) -> Self { Self(val) } -} - -impl From for u64 { - fn from(short_id: ShortId) -> Self { short_id.0 } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn short_id_is_onchain() { - let test_cases = vec![ - 0, - 1, - 100, - 16, - 32, - 40, - 0x7FFF_FF00_0000_0000, - 0x0000_0000_0000_8000, - ]; - for c in &test_cases { - let sid = ShortId(*c); - assert!(sid.is_onchain()); - } - } - - #[test] - fn short_id_is_offchain() { - let test_cases = vec![ - 0x8000_0000_0000_0000, - 0x8000_0000_0000_0001, - 0x9000_0000_0000_0000, - 0xFFFF_0000_0000_0000, - ]; - for c in &test_cases { - let sid = ShortId(*c); - assert!(sid.is_offchain()); - } - } - - #[test] - fn short_id_into() { - let test_cases = [0, 1]; - for c in &test_cases { - let sid = ShortId(*c); - assert_eq!(sid.into_u64(), *c); - } - } - - #[test] - fn short_id_get_descriptor_empty() { - let sid = ShortId(0); - let descriptor = sid.get_descriptor(); - match descriptor.get_block_height() { - Some(h) => assert_eq!(h, 0), - None => {} - } - } - - #[test] - fn short_id_get_descriptor_block_height_valid() { - let test_cases = [ - [0x0000_0100_0000_0000, 1], - [0x0000_1000_0000_0000, 16], - [0x0001_0000_0000_0000, 256], - ]; - for c in &test_cases { - let sid = ShortId(c[0]); - match sid.get_descriptor().get_block_height() { - Some(h) => assert_eq!(u64::from(h), c[1]), - None => {} - } - } - } - - #[test] - #[cfg(not(codecov))] - #[should_panic(expected = "attempt to subtract with overflow")] - fn short_id_get_descriptor_block_height_overflow() { - let sid = ShortId(0x0000_0000_1000_0000); - sid.get_descriptor().get_block_height(); - } -} diff --git a/legacy/taptree.rs b/legacy/taptree.rs deleted file mode 100644 index da4f598..0000000 --- a/legacy/taptree.rs +++ /dev/null @@ -1,372 +0,0 @@ -// Deterministic bitcoin commitments library, implementing LNPBP standards -// Part of bitcoin protocol core library (BP Core Lib) -// -// Written in 2020-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the Apache 2.0 License -// along with this software. -// If not, see . - -//! `EmbedCommit: TapTree, Msg -> TapTree', TapNode` - -use core::fmt::Debug; -use core::hash::Hash; - -use bp::TapLeafHash; -use commit_verify::{ - lnpbp4, CommitVerify, EmbedCommitProof, EmbedCommitVerify, -}; - -use super::{Lnpbp6, TapretNodePartner, TapretPathProof}; -use crate::tapret::TapretPathError; - -// TODO: Re-check the use of all error variants -/// Errors during tapret commitment embedding into tapscript tree. -#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum TapretTreeError { - /// the provided commitment data can't be strict encoded. Details: {0} - #[from] - StrictEncoding(strict_encoding::Error), - - /// unable to update tap tree with the commitment. Details: {0} - #[from] - TapTree(TaprootBuilderError), - - /// the taproot script tree is invalid. Details: {0} - #[from] - TreeBuilder(IncompleteTapTree), - - /// the tapret commitment is impossible since the taproot script tree - /// already has the maximal depth. - #[from(MaxDepthExceeded)] - MaxDepthExceeded, - - /// the provided taproot script tree has no revealed nodes to prove the - /// commitment. - IncompleteTree(TaprootScriptTree), - - /// tapret node partner {0} contains alternative commitment - AlternativeCommitment(TapretNodePartner), - - /// tapret node partner {0} has an invalid order with the commitment node - /// {1} - IncorrectOrdering(TapretNodePartner, TapLeafHash), -} - -/// Errors during taproot script tree tapret commitment verification and -/// restoration of the original container structure. -#[derive( - Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, Error, From -)] -#[display(doc_comments)] -pub enum TapretProofError { - /// the provided tapret proof does not contain a taproot script tree, i.e. - /// can't contain a commitment - EmptyTree, - - /// the provided tapret proof consists of a single node - #[from(UnsplittableTree)] - UnsplittableTree, - - /// Errors in the taproot script tree and tapret path proof - /// correspondences. See [`TapretSourceError`] for details. - #[from] - #[display(inner)] - SourceError(TapretSourceError), -} - -impl From for TapretProofError { - fn from(err: CutError) -> Self { - match err { - CutError::UnsplittableTree => Self::UnsplittableTree, - CutError::DfsTraversal(e) => Self::SourceError(e.into()), - } - } -} - -/// Errors during taproot script tree tapret commitment ebmedding. -#[derive( - Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, Error, From -)] -#[display(doc_comments)] -pub enum TapretSourceError { - /// the length of the constructed tapret path proof exceeds taproot path - /// length limit. - #[from(MaxDepthExceeded)] - MaxDepthExceeded, - - /// the node partner {0} at the level 1 can't be proven not to contain an - /// alternative tapret commitment. - InvalidNodePartner(TapretNodePartner), - - /// unable to produce tapret commitment since the commitment path {0} does - /// not exist within the tree. - PathNotExists(DfsPath), - - /// the provided taproot script tree contains hidden node {0} at path {1} - /// and can't be used for tapret commit instillation. - HiddenNode(TapNodeHash, DfsPath), - - /// the provided tapret commitment path {1} points at the leaf node {0} - /// and can't be used for tapret commit instillation. - LeafNode(LeafScript, DfsPath), -} - -impl From for TapretSourceError { - fn from(err: InstillError) -> Self { - match err { - InstillError::MaxDepthExceeded => Self::MaxDepthExceeded, - InstillError::DfsTraversal(e) => e.into(), - } - } -} - -impl From for TapretSourceError { - fn from(err: DfsTraversalError) -> Self { - match err { - DfsTraversalError::PathNotExists(path) => Self::PathNotExists(path), - DfsTraversalError::HiddenNode { - node_hash, - failed_path, - path_leftover: _, - } => Self::HiddenNode(node_hash, failed_path), - DfsTraversalError::LeafNode { - leaf_script, - failed_path, - path_leftover: _, - } => Self::LeafNode(leaf_script, failed_path), - } - } -} - -impl From for TapretSourceError { - fn from(err: TapretPathError) -> Self { - match err { - TapretPathError::MaxDepthExceeded => Self::MaxDepthExceeded, - TapretPathError::InvalidNodePartner(partner) => { - Self::InvalidNodePartner(partner) - } - } - } -} - -/// Structure wrapping concrete taproot script tree, acting as a source of the -/// tapret commitment, keeping information about DFS path which should be used -/// for embedding tapret commit. -/// -/// The structure can be used with [`TapTree`] and [`TaprootScriptTree`]. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct TapretSourceInfo(Option) -where - Tree: Clone + Eq + Debug; - -impl TapretSourceInfo { - /// Validates that the provided path can be used for a tapret commitment - /// embedding and constructs [`SourceTree`] from the provided - /// [`TaprootScriptTree`] and a valid path. The path must point to a branch - /// node in the tree. - /// - /// # Errors - /// - /// The following errors may happen: - /// - [`DfsPathError::PathNotExists`], if the path does not exists within - /// the tree; - /// - [`DfsPathError::HiddenNode`], if the path passes through a hidden node - /// of the tree; - /// - [`DfsPathError::LeafNode`], if the path points at a leaf node. - pub fn with( - tap_tree: Option, - ) -> Result { - Ok(TapretSourceInfo(tap_tree)) - } - - /// Returns reference to the script tree root node, if taproot script tree - /// is present in the source data. - pub fn as_root_node(&self) -> Option<&TreeNode> { - self.0.as_ref().map(TaprootScriptTree::as_root_node) - } - - /// Releases internal [`TapTree`] data, if present. - #[inline] - pub fn into_tap_tree(self) -> Option { self.0.map(TapTree::from) } -} - -impl TapretSourceInfo { - /// Validates that the provided path can be used for a tapret commitment - /// embedding and constructs [`SourceTree`] from the provided [`TapTree`] - /// and a valid path. The path must point to a branch node in the tree. - /// - /// # Errors - /// - /// The following errors may happen: - /// - [`DfsPathError::PathNotExists`], if the path does not exists within - /// the tree; - /// - [`DfsPathError::HiddenNode`], if the path passes through a hidden node - /// of the tree; - /// - [`DfsPathError::LeafNode`], if the path points at a leaf node. - #[inline] - pub fn with(tap_tree: Option) -> Result { - TapretSourceInfo::::with( - tap_tree.map(TaprootScriptTree::from), - ) - .map(TapretSourceInfo::from) - } - - /// Releases internal [`TapTree`] data, if present. - #[inline] - pub fn into_tap_tree(self) -> Option { self.0 } -} - -impl From<&TapretSourceInfo> for TapretSourceInfo { - fn from(source: &TapretSourceInfo) -> Self { - let tap_tree = source.0.as_ref().cloned().map(TaprootScriptTree::from); - TapretSourceInfo(tap_tree) - } -} - -impl From> for TapretSourceInfo { - fn from(source: TapretSourceInfo) -> Self { - let tap_tree = source.0.map(TapTree::from); - TapretSourceInfo(tap_tree) - } -} - -impl - EmbedCommitProof< - lnpbp4::CommitmentHash, - TapretSourceInfo, - Lnpbp6, - > for TapretPathProof -{ - fn restore_original_container( - &self, - modified_tree: &TapretSourceInfo, - ) -> Result, TapretProofError> { - let tap_tree = modified_tree - .0 - .as_ref() - .cloned() - .ok_or(TapretProofError::EmptyTree)?; - - match self.partner_node { - // Taproot has key-only spending - None => Ok(TapretSourceInfo(None)), - // Taproot has script spendings - Some(_) => { - let (original_tree, _) = tap_tree.split()?; - Ok(TapretSourceInfo(Some(original_tree))) - } - } - } -} - -impl EmbedCommitVerify - for TapretSourceInfo -{ - type Proof = TapretPathProof; - type CommitError = TapretSourceError; - type VerifyError = TapretProofError; - - fn embed_commit( - &mut self, - msg: &lnpbp4::CommitmentHash, - ) -> Result { - for nonce in 0..=u8::MAX { - let commitment_script = TapScript::commit(&(*msg, nonce)); - - let commitment_node = - TreeNode::with_tap_script(commitment_script, 0); - let commitment_subtree = TaprootScriptTree::with(commitment_node) - .expect("invalid commitment node construction"); - - let tap_tree = if let Some(ref mut tap_tree) = self.0 { - tap_tree - } else { - self.0 = Some(commitment_subtree); - return Ok(TapretPathProof::new()); - }; - - let original_tree = tap_tree.clone(); - *tap_tree = - original_tree.join(commitment_subtree, DfsOrder::Last)?; - - let branch = tap_tree - .as_root_node() - .as_branch() - .expect("instill algorithm is broken"); - let partner = branch.as_dfs_child_node(DfsOrder::First); - - let partner_is_left_node = - branch.dfs_ordering() == DfsOrdering::LeftRight; - - let partner_proof = match (partner_is_left_node, partner) { - (true, node) => TapretNodePartner::LeftNode(node.node_hash()), - (false, TreeNode::Leaf(script, _)) => { - TapretNodePartner::RightLeaf(script.clone()) - } - (false, TreeNode::Hidden(partner_hash, _)) => { - return Err(TapretSourceError::HiddenNode( - *partner_hash, - vec![DfsOrder::First].into(), - )) - } - (false, TreeNode::Branch(partner_branch, _)) => { - TapretNodePartner::right_branch( - partner_branch.as_left_node().node_hash(), - partner_branch.as_right_node().node_hash(), - ) - } - }; - - if partner_is_left_node || nonce == u8::MAX { - return TapretPathProof::with(partner_proof, nonce) - .map_err(TapretSourceError::from); - } - } - unreachable!("for cycle always returns before exiting") - } -} - -impl EmbedCommitProof, Lnpbp6> - for TapretPathProof -{ - fn restore_original_container( - &self, - modified_container: &TapretSourceInfo, - ) -> Result, TapretProofError> { - EmbedCommitProof::< - _, - TapretSourceInfo, - _, - >::restore_original_container( - self, &modified_container.into() - ).map(TapretSourceInfo::into) - } -} - -impl EmbedCommitVerify - for TapretSourceInfo -{ - type Proof = TapretPathProof; - type CommitError = TapretSourceError; - type VerifyError = TapretProofError; - - fn embed_commit( - &mut self, - msg: &lnpbp4::CommitmentHash, - ) -> Result { - let mut source = TapretSourceInfo::::from( - self as &TapretSourceInfo<_>, - ); - let proof = source.embed_commit(msg)?; - *self = source.into(); - Ok(proof) - } -} diff --git a/psbt/Cargo.toml b/psbt/Cargo.toml new file mode 100644 index 0000000..5ad6029 --- /dev/null +++ b/psbt/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "psbt" +version = { workspace = true } +description = "Modern, minimalistic & standard-compliant PSBT library" +keywords = { workspace = true } +categories = { workspace = true } +readme = "../README.md" +authors = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } + +[dependencies] +amplify = { workspace = true } +bp-std = { path = "../std" } +serde_crate = { workspace = true, optional = true } + +[features] +default = [] +all = ["serde"] +serde = ["serde_crate", "bp-std/serde"] diff --git a/psbt/src/lib.rs b/psbt/src/lib.rs new file mode 100644 index 0000000..fa51f7a --- /dev/null +++ b/psbt/src/lib.rs @@ -0,0 +1,21 @@ +// Modern, minimalistic & standard-compliant cold wallet library. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2020-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2020-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2020-2023 Dr Maxim Orlovsky. 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. diff --git a/src/lib.rs b/src/lib.rs index 5c27dc0..6ed2597 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,37 +20,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[macro_use] -extern crate amplify; -#[cfg(feature = "serde")] -#[macro_use] -extern crate serde_crate as serde; -pub extern crate bitcoin_hashes as hashes; - -mod base58; -mod index; -mod path; -mod key; -mod xpub; -mod descriptors; -mod address; -mod derive; -mod chain; -mod wallet; - -pub use address::{ - Address, AddressNetwork, AddressParseError, AddressPayload, AddressType, PubkeyHash, - ScriptHash, WPubkeyHash, WScriptHash, -}; -pub use bc::{secp256k1, *}; -pub use chain::{AddrInfo, BlockInfo, MiningInfo, TxInInfo, TxInfo, TxOutInfo, TxStatus, UtxoInfo}; -pub use derive::{Derive, DeriveCompr, DeriveXOnly}; -pub use descriptors::TrKey; -pub use index::{ - DerivationIndex, HardenedIndex, Idx, IndexError, IndexParseError, NormalIndex, - HARDENED_INDEX_BOUNDARY, -}; -pub use key::{ComprPubkey, LegacyPubkey, TaprootPubkey, UncomprPubkey}; -pub use path::{DerivationParseError, DerivationPath}; -pub use wallet::{Wallet, WalletCache, WalletData, WalletDescr}; -pub use xpub::{Xpub, XpubDescriptor, XpubFp, XpubId, XpubMeta}; +pub use bpstd::*; diff --git a/std/Cargo.toml b/std/Cargo.toml new file mode 100644 index 0000000..0469e29 --- /dev/null +++ b/std/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bp-std" +version = { workspace = true } +description = "Modern, minimalistic & standard-compliant cold wallet library" +keywords = { workspace = true } +categories = { workspace = true } +readme = "../README.md" +authors = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } + +[lib] +name = "bpstd" + +[dependencies] +amplify = { workspace = true } +bitcoin_hashes = "0.12.0" +bech32 = { workspace = true } +bp-primitives = { workspace = true } +serde_crate = { workspace = true, optional = true } + +[features] +default = [] +all = ["serde"] +serde = ["serde_crate", "bp-primitives/serde"] diff --git a/src/address.rs b/std/src/address.rs similarity index 100% rename from src/address.rs rename to std/src/address.rs diff --git a/src/base58.rs b/std/src/base58.rs similarity index 100% rename from src/base58.rs rename to std/src/base58.rs diff --git a/src/chain.rs b/std/src/chain.rs similarity index 100% rename from src/chain.rs rename to std/src/chain.rs diff --git a/src/derive.rs b/std/src/derive.rs similarity index 100% rename from src/derive.rs rename to std/src/derive.rs diff --git a/src/descriptors.rs b/std/src/descriptors.rs similarity index 100% rename from src/descriptors.rs rename to std/src/descriptors.rs diff --git a/src/index.rs b/std/src/index.rs similarity index 100% rename from src/index.rs rename to std/src/index.rs diff --git a/src/key.rs b/std/src/key.rs similarity index 100% rename from src/key.rs rename to std/src/key.rs diff --git a/std/src/lib.rs b/std/src/lib.rs new file mode 100644 index 0000000..5c27dc0 --- /dev/null +++ b/std/src/lib.rs @@ -0,0 +1,56 @@ +// Modern, minimalistic & standard-compliant cold wallet library. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2020-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2020-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2020-2023 Dr Maxim Orlovsky. 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. + +#[macro_use] +extern crate amplify; +#[cfg(feature = "serde")] +#[macro_use] +extern crate serde_crate as serde; +pub extern crate bitcoin_hashes as hashes; + +mod base58; +mod index; +mod path; +mod key; +mod xpub; +mod descriptors; +mod address; +mod derive; +mod chain; +mod wallet; + +pub use address::{ + Address, AddressNetwork, AddressParseError, AddressPayload, AddressType, PubkeyHash, + ScriptHash, WPubkeyHash, WScriptHash, +}; +pub use bc::{secp256k1, *}; +pub use chain::{AddrInfo, BlockInfo, MiningInfo, TxInInfo, TxInfo, TxOutInfo, TxStatus, UtxoInfo}; +pub use derive::{Derive, DeriveCompr, DeriveXOnly}; +pub use descriptors::TrKey; +pub use index::{ + DerivationIndex, HardenedIndex, Idx, IndexError, IndexParseError, NormalIndex, + HARDENED_INDEX_BOUNDARY, +}; +pub use key::{ComprPubkey, LegacyPubkey, TaprootPubkey, UncomprPubkey}; +pub use path::{DerivationParseError, DerivationPath}; +pub use wallet::{Wallet, WalletCache, WalletData, WalletDescr}; +pub use xpub::{Xpub, XpubDescriptor, XpubFp, XpubId, XpubMeta}; diff --git a/src/path.rs b/std/src/path.rs similarity index 100% rename from src/path.rs rename to std/src/path.rs diff --git a/src/wallet.rs b/std/src/wallet.rs similarity index 100% rename from src/wallet.rs rename to std/src/wallet.rs diff --git a/src/xpub.rs b/std/src/xpub.rs similarity index 100% rename from src/xpub.rs rename to std/src/xpub.rs