From c44a261864ffd10603da357881d1ee8ca9e346d1 Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 24 Jun 2022 17:47:21 -0400 Subject: [PATCH 1/3] Use WIF private keys and other improvements --- Cargo.lock | 66 -------------------------- Cargo.toml | 1 - src/main.rs | 7 +-- src/nft.rs | 24 +++------- src/subcommand/generate_private_key.rs | 19 +++----- src/subcommand/mint.rs | 6 +-- tests/nft.rs | 6 +-- 7 files changed, 23 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ceb6252ad..4bcbfcff2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,15 +243,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array", -] - [[package]] name = "bstr" version = "0.2.17" @@ -415,15 +406,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.3.2" @@ -514,16 +496,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "crypto-common" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "csv" version = "1.1.6" @@ -578,16 +550,6 @@ dependencies = [ "syn", ] -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dirs" version = "4.0.0" @@ -830,16 +792,6 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.1.16" @@ -1592,7 +1544,6 @@ dependencies = [ "serde", "serde_cbor", "serde_json", - "sha2", "tempfile", "tokio", "tower-http", @@ -2248,17 +2199,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "slab" version = "0.4.6" @@ -2595,12 +2535,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - [[package]] name = "unicase" version = "2.6.0" diff --git a/Cargo.toml b/Cargo.toml index 49658c5a0f..600e1fe0db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ secp256k1 = { version = "0.22.1", features = ["rand", "rand-std", "global-conte serde = { version = "1.0.137", features = ["derive"] } serde_cbor = "0.11.2" serde_json = "1.0.81" -sha2 = "0.10.2" tokio = { version = "1.17.0", features = ["rt-multi-thread"] } tower-http = { version = "0.3.3", features = ["cors"] } diff --git a/src/main.rs b/src/main.rs index 8ebe9ed3f0..58bec7341a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,10 +11,11 @@ use { axum_server::Handle, bech32::{FromBase32, ToBase32}, bitcoin::{ - blockdata::constants::COIN_VALUE, consensus::Decodable, consensus::Encodable, Address, Block, - BlockHash, Network, OutPoint, Transaction, Txid, + blockdata::constants::COIN_VALUE, consensus::Decodable, consensus::Encodable, + util::key::PrivateKey, Address, Block, BlockHash, Network, + OutPoint, Transaction, Txid, }, - bitcoin_hashes::{sha256d, Hash, HashEngine}, + bitcoin_hashes::{sha256d, sha256, Hash, HashEngine}, chrono::{DateTime, NaiveDateTime, Utc}, clap::Parser, derive_more::{Display, FromStr}, diff --git a/src/nft.rs b/src/nft.rs index c1e6dfc982..b028f94272 100644 --- a/src/nft.rs +++ b/src/nft.rs @@ -11,7 +11,7 @@ pub(crate) struct Nft { #[derive(Serialize, Deserialize)] struct Metadata { - data_hash: sha256d::Hash, + data_hash: sha256::Hash, ordinal: Ordinal, public_key: XOnlyPublicKey, } @@ -20,7 +20,7 @@ impl Nft { const HRP: &'static str = "nft"; pub(crate) fn mint(ordinal: Ordinal, data: &[u8], signing_key_pair: KeyPair) -> Result { - let data_hash = sha256d::Hash::hash(data); + let data_hash = sha256::Hash::hash(data); let public_key = signing_key_pair.public_key(); @@ -58,22 +58,12 @@ impl Nft { .unwrap() } - pub(crate) fn issuer(&self) -> String { - bech32::encode( - "pubkey", - self.metadata.public_key.serialize().to_base32(), - bech32::Variant::Bech32m, - ) - .unwrap() + pub(crate) fn issuer(&self) -> XOnlyPublicKey { + self.metadata.public_key } - pub(crate) fn data_hash(&self) -> String { - bech32::encode( - "data", - self.metadata.data_hash.to_base32(), - bech32::Variant::Bech32m, - ) - .unwrap() + pub(crate) fn data_hash(&self) -> sha256::Hash { + self.metadata.data_hash } pub(crate) fn ordinal(&self) -> Ordinal { @@ -85,7 +75,7 @@ impl Nft { let nft = serde_cbor::from_slice::(&data)?; - let data_hash = sha256d::Hash::hash(&nft.data); + let data_hash = sha256::Hash::hash(&nft.data); if data_hash != nft.metadata.data_hash { return Err(anyhow!("NFT data hash does not match actual data_hash")); diff --git a/src/subcommand/generate_private_key.rs b/src/subcommand/generate_private_key.rs index c42c0bbe24..3a80a8a9cc 100644 --- a/src/subcommand/generate_private_key.rs +++ b/src/subcommand/generate_private_key.rs @@ -2,21 +2,14 @@ use super::*; pub(crate) fn run() -> Result { let mut rng = rand::thread_rng(); - let secp = Secp256k1::new(); - let secret_key = SecretKey::new(&mut rng); - let key_pair = KeyPair::from_secret_key(&secp, secret_key); - let public_key = key_pair.public_key(); - let address = Address::p2tr(&secp, public_key, None, Network::Bitcoin); + let private_key = PrivateKey { + compressed: true, + network: Network::Bitcoin, + inner: SecretKey::new(&mut rng), + }; - let private_key_bech32 = bech32::encode( - "privkey", - secret_key.as_ref().to_base32(), - bech32::Variant::Bech32m, - ) - .unwrap(); - - println!("{} {}", private_key_bech32, address); + println!("{}", private_key.to_wif()); Ok(()) } diff --git a/src/subcommand/mint.rs b/src/subcommand/mint.rs index 45dc7224ff..5500cf2f68 100644 --- a/src/subcommand/mint.rs +++ b/src/subcommand/mint.rs @@ -6,7 +6,7 @@ pub(crate) struct Mint { data_path: PathBuf, #[clap(long, help = "Assign NFT to ")] ordinal: Ordinal, - #[clap(long, help = "Sign NFT with bech32m-formatted ")] + #[clap(long, help = "Sign NFT with WIF-formatted ")] signing_key: String, #[clap(long, help = "Write signed NFT metadata to ")] output_path: PathBuf, @@ -17,12 +17,12 @@ impl Mint { let data = fs::read(&self.data_path) .with_context(|| format!("Failed to read data from {}", self.data_path.display()))?; - let secret_key = SecretKey::from_slice(&decode_bech32(&self.signing_key, "privkey")?)?; + let private_key = PrivateKey::from_wif(&self.signing_key)?; let nft = Nft::mint( self.ordinal, &data, - KeyPair::from_secret_key(&Secp256k1::new(), secret_key), + KeyPair::from_secret_key(&Secp256k1::new(), private_key.inner), )?; fs::write(&self.output_path, nft.encode()) diff --git a/tests/nft.rs b/tests/nft.rs index f277671cb2..76aafd3c81 100644 --- a/tests/nft.rs +++ b/tests/nft.rs @@ -9,7 +9,7 @@ fn mint_and_verify() -> Result { "--ordinal", "0", "--signing-key", - "privkey13jcd573rjnnx8nauuc26tec4qwxv7qnyd59f3nwyef65qyp9598s9p8hy6", + "KysB4eR1DjAmbf1qkiznwgd4xPy8yj66gHF4dBJmhFraoL1gjqZd", "--data-path", "data.txt", "--output-path", @@ -22,8 +22,8 @@ fn mint_and_verify() -> Result { .expected_stderr( "NFT is valid! Ordinal: 0 -Issuer: pubkey1ny8pdtw4ftxgn0p42cw00mvkjqlks4mk6ju5w9xcwatfhrh3at6qkrsmkm -Data hash: data1c7k73r785g2f3f49uhpctc0k30kcy2mj4f3uf2dy3gpvy3nwu20q97shse +Issuer: 1b7bb1348ae7a273e55644a920ecf4e5b7d8a5d0966c649e720601e73c737eb7 +Data hash: 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae ", ) .expected_stdout("foo") From be14fd27d5e3ef5131b00dd0f75e781de8187c3c Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 24 Jun 2022 17:55:28 -0400 Subject: [PATCH 2/3] Nuke bech32 --- src/decode_bech32.rs | 19 ------------------- src/main.rs | 3 +-- src/nft.rs | 17 ++++------------- src/subcommand/verify.rs | 2 +- 4 files changed, 6 insertions(+), 35 deletions(-) delete mode 100644 src/decode_bech32.rs diff --git a/src/decode_bech32.rs b/src/decode_bech32.rs deleted file mode 100644 index 6d56cfc910..0000000000 --- a/src/decode_bech32.rs +++ /dev/null @@ -1,19 +0,0 @@ -use super::*; - -pub(crate) fn decode_bech32(encoded: &str, expected_hrp: &str) -> Result> { - let (hrp, data, variant) = bech32::decode(encoded)?; - - if hrp != expected_hrp { - return Err(anyhow!( - "bech32 string should be have `{}` human-readable prefix but starts with `{}`", - expected_hrp, - hrp - )); - } - - if variant != bech32::Variant::Bech32m { - return Err(anyhow!("bech32 strings must use the bech32m variant",)); - } - - Ok(Vec::from_base32(&data)?) -} diff --git a/src/main.rs b/src/main.rs index 58bec7341a..ec81583a39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use { crate::{ - arguments::Arguments, bytes::Bytes, decode_bech32::decode_bech32, epoch::Epoch, height::Height, + arguments::Arguments, bytes::Bytes, epoch::Epoch, height::Height, index::Index, nft::Nft, options::Options, ordinal::Ordinal, sat_point::SatPoint, subcommand::Subcommand, }, @@ -56,7 +56,6 @@ use lmdb_database::{Database, WriteTransaction}; mod arguments; mod bytes; -mod decode_bech32; mod epoch; mod height; mod index; diff --git a/src/nft.rs b/src/nft.rs index b028f94272..0566d9ca53 100644 --- a/src/nft.rs +++ b/src/nft.rs @@ -17,8 +17,6 @@ struct Metadata { } impl Nft { - const HRP: &'static str = "nft"; - pub(crate) fn mint(ordinal: Ordinal, data: &[u8], signing_key_pair: KeyPair) -> Result { let data_hash = sha256::Hash::hash(data); @@ -49,13 +47,8 @@ impl Nft { &self.data } - pub(crate) fn encode(&self) -> String { - bech32::encode( - Self::HRP, - serde_cbor::to_vec(self).unwrap().to_base32(), - bech32::Variant::Bech32m, - ) - .unwrap() + pub(crate) fn encode(&self) -> Vec { + serde_cbor::to_vec(self).unwrap() } pub(crate) fn issuer(&self) -> XOnlyPublicKey { @@ -70,10 +63,8 @@ impl Nft { self.metadata.ordinal } - pub(crate) fn verify(encoded: &str) -> Result { - let data = decode_bech32(encoded, Self::HRP)?; - - let nft = serde_cbor::from_slice::(&data)?; + pub(crate) fn verify(cbor: &[u8]) -> Result { + let nft = serde_cbor::from_slice::(cbor)?; let data_hash = sha256::Hash::hash(&nft.data); diff --git a/src/subcommand/verify.rs b/src/subcommand/verify.rs index b4f6c3b84a..4ac7537558 100644 --- a/src/subcommand/verify.rs +++ b/src/subcommand/verify.rs @@ -8,7 +8,7 @@ pub(crate) struct Verify { impl Verify { pub(crate) fn run(self) -> Result { - let encoded = fs::read_to_string(&self.input_path) + let encoded = fs::read(&self.input_path) .with_context(|| format!("Failed to read NFT from `{}`", self.input_path.display()))?; let nft = Nft::verify(&encoded) From 41f4eee8058676df8cf10c0a8dc68c2de331cdcd Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 24 Jun 2022 17:56:52 -0400 Subject: [PATCH 3/3] Format --- src/main.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index ec81583a39..b953640de2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,8 @@ use { crate::{ - arguments::Arguments, bytes::Bytes, epoch::Epoch, height::Height, - index::Index, nft::Nft, options::Options, ordinal::Ordinal, sat_point::SatPoint, - subcommand::Subcommand, + arguments::Arguments, bytes::Bytes, epoch::Epoch, height::Height, index::Index, nft::Nft, + options::Options, ordinal::Ordinal, sat_point::SatPoint, subcommand::Subcommand, }, anyhow::{anyhow, Context, Error}, axum::{extract, http::StatusCode, response::IntoResponse, routing::get, Json, Router}, @@ -12,10 +11,9 @@ use { bech32::{FromBase32, ToBase32}, bitcoin::{ blockdata::constants::COIN_VALUE, consensus::Decodable, consensus::Encodable, - util::key::PrivateKey, Address, Block, BlockHash, Network, - OutPoint, Transaction, Txid, + util::key::PrivateKey, Address, Block, BlockHash, Network, OutPoint, Transaction, Txid, }, - bitcoin_hashes::{sha256d, sha256, Hash, HashEngine}, + bitcoin_hashes::{sha256, sha256d, Hash, HashEngine}, chrono::{DateTime, NaiveDateTime, Utc}, clap::Parser, derive_more::{Display, FromStr},