diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 368ab991..40fdfe7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,10 +10,6 @@ on: env: CARGO_TERM_COLOR: always - GOAT_CHAIN_URL: https://rpc.testnet3.goat.network - GOAT_GATEWAY_CONTRACT_ADDRESS: 0xeD8AeeD334fA446FA03Aa00B28aFf02FA8aC02df - GOAT_GATEWAY_CONTRACT_CREATION: 0 - GOAT_CHAIN_ID: 48816 jobs: fmt: @@ -51,6 +47,5 @@ jobs: toolchain: - nightly steps: - - name: Run UTs - uses: actions/checkout@v2 - run: cargo test -r + - uses: actions/checkout@v2 + - run: GOAT_CHAIN_URL=https://rpc.testnet3.goat.network GOAT_GATEWAY_CONTRACT_ADDRESS=0xeD8AeeD334fA446FA03Aa00B28aFf02FA8aC02df GOAT_GATEWAY_CONTRACT_CREATION=0 GOAT_CHAIN_ID=48816 cargo test -r diff --git a/crates/bitvm2/src/committee/api.rs b/crates/bitvm2/src/committee/api.rs index d4db7dee..442315fe 100644 --- a/crates/bitvm2/src/committee/api.rs +++ b/crates/bitvm2/src/committee/api.rs @@ -309,7 +309,7 @@ pub fn push_committee_pre_signatures( graph: &mut Bitvm2Graph, signed_witness: &[Witness; COMMITTEE_PRE_SIGN_NUM], ) -> Result<()> { - if graph.committee_pre_signed == true { + if graph.committee_pre_signed { bail!("already pre-signed by committee".to_string()) }; graph.take1.tx_mut().input[0].witness = signed_witness[0].clone(); diff --git a/crates/bitvm2/src/keys.rs b/crates/bitvm2/src/keys.rs index ae487bea..fcd2f41d 100644 --- a/crates/bitvm2/src/keys.rs +++ b/crates/bitvm2/src/keys.rs @@ -35,8 +35,7 @@ impl CommitteeMasterKey { NodeMasterKey(self.0).master_keypair() } pub fn keypair_for_instance(&self, instance_id: Uuid) -> Keypair { - let domain = - vec![b"committee_bitvm_key".to_vec(), instance_id.as_bytes().to_vec()].concat(); + let domain = [b"committee_bitvm_key".to_vec(), instance_id.as_bytes().to_vec()].concat(); let instance_seed = derive_secret(&self.0, &domain); generate_keypair_from_seed(instance_seed) } @@ -45,7 +44,7 @@ impl CommitteeMasterKey { instance_id: Uuid, graph_id: Uuid, ) -> [(SecNonce, PubNonce, Signature); COMMITTEE_PRE_SIGN_NUM] { - let domain = vec![ + let domain = [ b"committee_bitvm_nonces".to_vec(), instance_id.as_bytes().to_vec(), graph_id.as_bytes().to_vec(), @@ -69,8 +68,7 @@ impl OperatorMasterKey { self.master_keypair() } pub fn wots_keypair_for_graph(&self, graph_id: Uuid) -> (WotsSecretKeys, WotsPublicKeys) { - let domain = - vec![b"operator_bitvm_wots_key".to_vec(), graph_id.as_bytes().to_vec()].concat(); + let domain = [b"operator_bitvm_wots_key".to_vec(), graph_id.as_bytes().to_vec()].concat(); let wot_seed = derive_secret(&self.0, &domain); generate_wots_keys(&wot_seed) } diff --git a/crates/bitvm2/src/operator/api.rs b/crates/bitvm2/src/operator/api.rs index 1ccd9fe3..f29a52b9 100644 --- a/crates/bitvm2/src/operator/api.rs +++ b/crates/bitvm2/src/operator/api.rs @@ -137,7 +137,7 @@ pub fn sign_proof( ark_pubin: PublicInputs, wots_sec: &WotsSecretKeys, ) -> Groth16WotsSignatures { - generate_signatures_lit(ark_proof, ark_pubin, &ark_vkey, wots_sec.1.to_vec()).unwrap() + generate_signatures_lit(ark_proof, ark_pubin, ark_vkey, wots_sec.1.to_vec()).unwrap() } pub fn generate_bitvm_graph( @@ -264,7 +264,7 @@ pub fn generate_bitvm_graph( let assert_wots_pubkeys = ¶ms.operator_wots_pubkeys.1; let connector_d = ConnectorD::new(network, &committee_taproot_pubkey); let all_assert_commit_connectors_e = - AllCommitConnectorsE::new(network, &operator_pubkey, &assert_wots_pubkeys); + AllCommitConnectorsE::new(network, &operator_pubkey, assert_wots_pubkeys); let assert_init_input_0_vout: usize = 2; let assert_init_input_0 = Input { outpoint: OutPoint { txid: kickoff_txid, vout: assert_init_input_0_vout as u32 }, @@ -424,7 +424,7 @@ pub fn push_operator_pre_signature( graph: &mut Bitvm2Graph, signed_witness: &Witness, ) -> Result<()> { - if graph.operator_pre_signed == true { + if graph.operator_pre_signed { bail!("already pre-signed by operator".to_string()) }; graph.challenge.tx_mut().input[0].witness = signed_witness.clone(); @@ -442,7 +442,7 @@ pub fn operator_sign_kickoff( let kickoff_wots_commitment_keys = CommitmentMessageId::pubkey_map_for_kickoff(&operator_wots_pubkeys.0); let evm_txid_inputs = WinternitzSigningInputs { - message: &withdraw_evm_txid.to_vec(), + message: withdraw_evm_txid.as_ref(), signing_key: &operator_wots_seckeys.0[0], }; let connector_6 = Connector6::new( @@ -508,7 +508,7 @@ pub fn operator_sign_assert( let all_assert_commit_connectors_e = AllCommitConnectorsE::new( operator_context.network, &operator_context.operator_public_key, - &assert_wots_pubkeys, + assert_wots_pubkeys, ); graph.assert_commit.sign(&all_assert_commit_connectors_e, assert_commit_witness); diff --git a/crates/bitvm2/src/pegin.rs b/crates/bitvm2/src/pegin.rs index ba716660..0b355ac1 100644 --- a/crates/bitvm2/src/pegin.rs +++ b/crates/bitvm2/src/pegin.rs @@ -9,8 +9,8 @@ pub fn check_pegin_opreturn(network: &Network, script: &Script) -> bool { return false; } // Display decoded pushes - let mut instructions = script.instructions(); - while let Some(instr) = instructions.next() { + let instructions = script.instructions(); + for instr in instructions { match instr { Ok(script::Instruction::PushBytes(bytes)) => { println!("Data pushed: {}", hex::encode(bytes)); diff --git a/crates/bitvm2/src/types.rs b/crates/bitvm2/src/types.rs index 1aa6fef9..7615966f 100644 --- a/crates/bitvm2/src/types.rs +++ b/crates/bitvm2/src/types.rs @@ -259,7 +259,7 @@ pub mod node_serializer { serde::de::Error::custom(format!("Missing groth16pk.pub.[{}]", i)) })?; - if v.len() != W256_LEN as usize { + if v.len() != W256_LEN { return Err(serde::de::Error::custom("Invalid wots public-key length")); }; @@ -285,7 +285,7 @@ pub mod node_serializer { serde::de::Error::custom(format!("Missing groth16pk.wot256.[{}]", i)) })?; - if v.len() != W256_LEN as usize { + if v.len() != W256_LEN { return Err(serde::de::Error::custom("Invalid wots public-key length")); }; @@ -311,7 +311,7 @@ pub mod node_serializer { serde::de::Error::custom(format!("Missing groth16pk.wothash.[{}]", i)) })?; - if v.len() != WHASH_LEN as usize { + if v.len() != WHASH_LEN { return Err(serde::de::Error::custom("Invalid wots public-key length")); }; diff --git a/crates/bitvm2/src/verifier/api.rs b/crates/bitvm2/src/verifier/api.rs index c0475013..b2c3a38a 100644 --- a/crates/bitvm2/src/verifier/api.rs +++ b/crates/bitvm2/src/verifier/api.rs @@ -17,7 +17,7 @@ pub fn extract_proof_sigs_from_assert_commit_txns( assert_commit_txns: [Transaction; COMMIT_TX_NUM], ) -> Result { let raw_wits: Vec = - assert_commit_txns.iter().flat_map(|tx| get_commit_from_assert_commit_tx(tx)).collect(); + assert_commit_txns.iter().flat_map(get_commit_from_assert_commit_tx).collect(); Ok(utils_signatures_from_raw_witnesses(&raw_wits)) } @@ -28,7 +28,7 @@ pub fn verify_proof( disprove_scripts: &[Script; NUM_TAPS], wots_pubkeys: &WotsPublicKeys, ) -> Option<(usize, Script)> { - validate_assertions(&ark_vkey, proof_sigs, *wots_pubkeys.1, disprove_scripts) + validate_assertions(ark_vkey, proof_sigs, *wots_pubkeys.1, disprove_scripts) } // challenge has a pre-signed SinglePlusAnyoneCanPay input and output @@ -68,241 +68,253 @@ pub fn sign_disprove( Ok(graph.disprove.finalize()) } -#[test] -fn test_extract_proof() { - use crate::{ - committee, operator, - types::{Bitvm2Parameters, CustomInputs}, - verifier, - }; - use bitcoin::{Amount, Network, OutPoint, PrivateKey, PublicKey, Txid}; - use bitvm::chunk::api::NUM_TAPS; - use bitvm::treepp::*; - use goat::transactions::base::Input; - use goat::{contexts::base::generate_n_of_n_public_key, scripts::generate_burn_script_address}; - use musig2::{AggNonce, PartialSignature, PubNonce, SecNonce}; - use secp256k1::SECP256K1; - use std::str::FromStr; +#[cfg(test)] +mod tests { + #[test] + fn test_extract_proof() { + use crate::{ + committee, operator, + types::{Bitvm2Parameters, CustomInputs}, + verifier, + }; + use bitcoin::{Amount, Network, OutPoint, PrivateKey, PublicKey, Txid}; + use bitvm::chunk::api::NUM_TAPS; + use bitvm::treepp::*; + use goat::transactions::base::Input; + use goat::{ + contexts::base::generate_n_of_n_public_key, scripts::generate_burn_script_address, + }; + use musig2::{AggNonce, PartialSignature, PubNonce, SecNonce}; + use secp256k1::SECP256K1; + use std::str::FromStr; - let network = Network::Testnet; - // key generation - println!("\ngenerate keypairs"); - const OPERATOR_SECRET: &str = - "3076ca1dfc1e383be26d5dd3c0c427340f96139fa8c2520862cf551ec2d670ac"; - const VERIFIER_0_SECRET: &str = - "ee0817eac0c13aa8ee2dd3256304041f09f0499d1089b56495310ae8093583e2"; - const VERIFIER_1_SECRET: &str = - "fc294c70faf210d4d0807ea7a3dba8f7e41700d90c119e1ae82a0687d89d297f"; + let network = Network::Testnet; + // key generation + println!("\ngenerate keypairs"); + const OPERATOR_SECRET: &str = + "3076ca1dfc1e383be26d5dd3c0c427340f96139fa8c2520862cf551ec2d670ac"; + const VERIFIER_0_SECRET: &str = + "ee0817eac0c13aa8ee2dd3256304041f09f0499d1089b56495310ae8093583e2"; + const VERIFIER_1_SECRET: &str = + "fc294c70faf210d4d0807ea7a3dba8f7e41700d90c119e1ae82a0687d89d297f"; - let verifier_0_keypair = committee::generate_keypair_from_seed(VERIFIER_0_SECRET.to_string()); - let verifier_1_keypair = committee::generate_keypair_from_seed(VERIFIER_1_SECRET.to_string()); - let operator_keypair = committee::generate_keypair_from_seed(OPERATOR_SECRET.to_string()); + let verifier_0_keypair = + committee::generate_keypair_from_seed(VERIFIER_0_SECRET.to_string()); + let verifier_1_keypair = + committee::generate_keypair_from_seed(VERIFIER_1_SECRET.to_string()); + let operator_keypair = committee::generate_keypair_from_seed(OPERATOR_SECRET.to_string()); - let verifier_0_sk = PrivateKey::new(verifier_0_keypair.secret_key(), network); - let verifier_0_public_key = PublicKey::from_private_key(SECP256K1, &verifier_0_sk); - let verifier_1_sk = PrivateKey::new(verifier_1_keypair.secret_key(), network); - let verifier_1_public_key = PublicKey::from_private_key(SECP256K1, &verifier_1_sk); - let operator_sk = PrivateKey::new(operator_keypair.secret_key(), network); - let operator_pubkey = PublicKey::from_private_key(SECP256K1, &operator_sk); + let verifier_0_sk = PrivateKey::new(verifier_0_keypair.secret_key(), network); + let verifier_0_public_key = PublicKey::from_private_key(SECP256K1, &verifier_0_sk); + let verifier_1_sk = PrivateKey::new(verifier_1_keypair.secret_key(), network); + let verifier_1_public_key = PublicKey::from_private_key(SECP256K1, &verifier_1_sk); + let operator_sk = PrivateKey::new(operator_keypair.secret_key(), network); + let operator_pubkey = PublicKey::from_private_key(SECP256K1, &operator_sk); - let mut committee_pubkeys: Vec = Vec::new(); - committee_pubkeys.push(verifier_0_public_key); - committee_pubkeys.push(verifier_1_public_key); - let (committee_agg_pubkey, _) = generate_n_of_n_public_key(&committee_pubkeys); + let mut committee_pubkeys: Vec = Vec::new(); + committee_pubkeys.push(verifier_0_public_key); + committee_pubkeys.push(verifier_1_public_key); + let (committee_agg_pubkey, _) = generate_n_of_n_public_key(&committee_pubkeys); - let (operator_wots_seckeys, operator_wots_pubkeys) = - operator::generate_wots_keys(OPERATOR_SECRET); + let (operator_wots_seckeys, operator_wots_pubkeys) = + operator::generate_wots_keys(OPERATOR_SECRET); - // mock graph data - println!("\ngenerate mock graph"); - let graph_index = 1; - let pegin_amount = Amount::from_btc(1.0).unwrap(); - let stake_amount = Amount::from_btc(0.2).unwrap(); - let challenge_amount = Amount::from_btc(0.1).unwrap(); - let fee_amount = Amount::from_sat(2000); - let mock_input = Input { - outpoint: OutPoint { - txid: Txid::from_str( - "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", - ) - .unwrap(), - vout: 0, - }, - amount: Amount::from_btc(10000.0).unwrap(), - }; - let user_inputs = CustomInputs { - inputs: vec![mock_input.clone()], - input_amount: pegin_amount, - fee_amount, - change_address: generate_burn_script_address(network), - }; - let operator_inputs = CustomInputs { - inputs: vec![mock_input], - input_amount: stake_amount, - fee_amount, - change_address: generate_burn_script_address(network), - }; - let params = Bitvm2Parameters { - network, - depositor_evm_address: [0xff; 20], - pegin_amount, - stake_amount, - challenge_amount, - committee_pubkeys, - committee_agg_pubkey, - operator_pubkey, - operator_wots_pubkeys: operator_wots_pubkeys.clone(), - user_inputs, - operator_inputs, - }; + // mock graph data + println!("\ngenerate mock graph"); + let graph_index = 1; + let pegin_amount = Amount::from_btc(1.0).unwrap(); + let stake_amount = Amount::from_btc(0.2).unwrap(); + let challenge_amount = Amount::from_btc(0.1).unwrap(); + let fee_amount = Amount::from_sat(2000); + let mock_input = Input { + outpoint: OutPoint { + txid: Txid::from_str( + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + ) + .unwrap(), + vout: 0, + }, + amount: Amount::from_btc(10000.0).unwrap(), + }; + let user_inputs = CustomInputs { + inputs: vec![mock_input.clone()], + input_amount: pegin_amount, + fee_amount, + change_address: generate_burn_script_address(network), + }; + let operator_inputs = CustomInputs { + inputs: vec![mock_input], + input_amount: stake_amount, + fee_amount, + change_address: generate_burn_script_address(network), + }; + let params = Bitvm2Parameters { + network, + depositor_evm_address: [0xff; 20], + pegin_amount, + stake_amount, + challenge_amount, + committee_pubkeys, + committee_agg_pubkey, + operator_pubkey, + operator_wots_pubkeys: operator_wots_pubkeys.clone(), + user_inputs, + operator_inputs, + }; - let mock_script = script! {OP_TRUE}; - let mock_script_bytes = mock_script.compile().to_bytes(); - let mock_disprove_scripts_bytes: [Vec; NUM_TAPS] = - std::array::from_fn(|_| mock_script_bytes.clone()); + let mock_script = script! {OP_TRUE}; + let mock_script_bytes = mock_script.compile().to_bytes(); + let mock_disprove_scripts_bytes: [Vec; NUM_TAPS] = + std::array::from_fn(|_| mock_script_bytes.clone()); - let mut graph = - operator::generate_bitvm_graph(params, mock_disprove_scripts_bytes.to_vec()).unwrap(); + let mut graph = + operator::generate_bitvm_graph(params, mock_disprove_scripts_bytes.to_vec()).unwrap(); - // opeartor pre-sign - println!("\nopeartor pre-sign"); - let _ = operator::operator_pre_sign(operator_keypair, &mut graph); + // opeartor pre-sign + println!("\nopeartor pre-sign"); + let _ = operator::operator_pre_sign(operator_keypair, &mut graph); - // committee pre-sign - println!("\ncommittee pre-sign"); - let verifier_0_nonces = committee::generate_nonce_from_seed( - VERIFIER_0_SECRET.to_string(), - graph_index, - verifier_0_keypair, - ); - let verifier_1_nonces = committee::generate_nonce_from_seed( - VERIFIER_1_SECRET.to_string(), - graph_index, - verifier_1_keypair, - ); + // committee pre-sign + println!("\ncommittee pre-sign"); + let verifier_0_nonces = committee::generate_nonce_from_seed( + VERIFIER_0_SECRET.to_string(), + graph_index, + verifier_0_keypair, + ); + let verifier_1_nonces = committee::generate_nonce_from_seed( + VERIFIER_1_SECRET.to_string(), + graph_index, + verifier_1_keypair, + ); - let verifier_0_sec_nonces: [SecNonce; committee::COMMITTEE_PRE_SIGN_NUM] = - std::array::from_fn(|i| verifier_0_nonces[i].0.clone()); - let verifier_0_pub_nonces: [PubNonce; committee::COMMITTEE_PRE_SIGN_NUM] = - std::array::from_fn(|i| verifier_0_nonces[i].1.clone()); + let verifier_0_sec_nonces: [SecNonce; committee::COMMITTEE_PRE_SIGN_NUM] = + std::array::from_fn(|i| verifier_0_nonces[i].0.clone()); + let verifier_0_pub_nonces: [PubNonce; committee::COMMITTEE_PRE_SIGN_NUM] = + std::array::from_fn(|i| verifier_0_nonces[i].1.clone()); - let verifier_1_sec_nonces: [SecNonce; committee::COMMITTEE_PRE_SIGN_NUM] = - std::array::from_fn(|i| verifier_1_nonces[i].0.clone()); - let verifier_1_pub_nonces: [PubNonce; committee::COMMITTEE_PRE_SIGN_NUM] = - std::array::from_fn(|i| verifier_1_nonces[i].1.clone()); - - let agg_nonces: [AggNonce; committee::COMMITTEE_PRE_SIGN_NUM] = verifier_0_pub_nonces - .iter() - .zip(verifier_1_pub_nonces) - .map(|(a, b)| committee::nonce_aggregation(&vec![a.clone(), b])) - .collect::>() - .try_into() - .unwrap(); + let verifier_1_sec_nonces: [SecNonce; committee::COMMITTEE_PRE_SIGN_NUM] = + std::array::from_fn(|i| verifier_1_nonces[i].0.clone()); + let verifier_1_pub_nonces: [PubNonce; committee::COMMITTEE_PRE_SIGN_NUM] = + std::array::from_fn(|i| verifier_1_nonces[i].1.clone()); - let verifier_0_sigs = committee::committee_pre_sign( - verifier_0_keypair, - verifier_0_sec_nonces, - agg_nonces.clone(), - &graph, - ) - .unwrap(); - - let verifier_1_sigs = committee::committee_pre_sign( - verifier_1_keypair, - verifier_1_sec_nonces, - agg_nonces.clone(), - &graph, - ) - .unwrap(); - - let committee_partial_sigs: [Vec; committee::COMMITTEE_PRE_SIGN_NUM] = - verifier_0_sigs + let agg_nonces: [AggNonce; committee::COMMITTEE_PRE_SIGN_NUM] = verifier_0_pub_nonces .iter() - .zip(verifier_1_sigs) - .map(|(&a, b)| vec![a, b]) - .collect::>>() + .zip(verifier_1_pub_nonces) + .map(|(a, b)| committee::nonce_aggregation(&vec![a.clone(), b])) + .collect::>() .try_into() .unwrap(); - let _ = - committee::signature_aggregation_and_push(&committee_partial_sigs, &agg_nonces, &mut graph); + let verifier_0_sigs = committee::committee_pre_sign( + verifier_0_keypair, + verifier_0_sec_nonces, + agg_nonces.clone(), + &graph, + ) + .unwrap(); + + let verifier_1_sigs = committee::committee_pre_sign( + verifier_1_keypair, + verifier_1_sec_nonces, + agg_nonces.clone(), + &graph, + ) + .unwrap(); + + let committee_partial_sigs: [Vec; committee::COMMITTEE_PRE_SIGN_NUM] = + verifier_0_sigs + .iter() + .zip(verifier_1_sigs) + .map(|(&a, b)| vec![a, b]) + .collect::>>() + .try_into() + .unwrap(); - let vk_bytes = [ - 115, 158, 251, 51, 106, 255, 102, 248, 22, 171, 229, 158, 80, 192, 240, 217, 99, 162, 65, - 107, 31, 137, 197, 79, 11, 210, 74, 65, 65, 203, 243, 14, 123, 2, 229, 125, 198, 247, 76, - 241, 176, 116, 6, 3, 241, 1, 134, 195, 39, 5, 124, 47, 31, 43, 164, 48, 120, 207, 150, 125, - 108, 100, 48, 155, 137, 132, 16, 193, 139, 74, 179, 131, 42, 119, 25, 185, 98, 13, 235, - 118, 92, 11, 154, 142, 134, 220, 191, 220, 169, 250, 244, 104, 123, 7, 247, 33, 178, 155, - 121, 59, 75, 188, 206, 198, 182, 97, 0, 64, 231, 45, 55, 92, 100, 17, 56, 159, 79, 13, 219, - 221, 33, 39, 193, 24, 36, 58, 105, 8, 70, 206, 176, 209, 146, 45, 201, 157, 226, 84, 213, - 135, 143, 178, 156, 112, 137, 246, 123, 248, 215, 168, 51, 95, 177, 47, 57, 29, 199, 224, - 98, 48, 144, 253, 15, 201, 192, 142, 62, 143, 13, 228, 89, 51, 58, 6, 226, 139, 99, 207, - 22, 113, 215, 79, 91, 158, 166, 210, 28, 90, 218, 111, 151, 4, 55, 230, 76, 90, 209, 149, - 113, 248, 245, 50, 231, 137, 51, 157, 40, 29, 184, 198, 201, 108, 199, 89, 67, 136, 239, - 96, 216, 237, 172, 29, 84, 3, 128, 240, 2, 218, 169, 217, 118, 179, 34, 226, 19, 227, 59, - 193, 131, 108, 20, 113, 46, 170, 196, 156, 45, 39, 151, 218, 22, 132, 250, 209, 183, 46, - 249, 115, 239, 14, 176, 200, 134, 158, 148, 139, 212, 167, 152, 205, 183, 236, 242, 176, - 96, 177, 187, 184, 252, 14, 226, 127, 127, 173, 147, 224, 220, 8, 29, 63, 73, 215, 92, 161, - 110, 20, 154, 131, 23, 217, 116, 145, 196, 19, 167, 84, 185, 16, 89, 175, 180, 110, 116, - 57, 198, 237, 147, 183, 164, 169, 220, 172, 52, 68, 175, 113, 244, 62, 104, 134, 215, 99, - 132, 199, 139, 172, 108, 143, 25, 238, 201, 128, 85, 24, 73, 30, 186, 142, 186, 201, 79, 3, - 176, 185, 70, 66, 89, 127, 188, 158, 209, 83, 17, 22, 187, 153, 8, 63, 58, 174, 236, 132, - 226, 43, 145, 97, 242, 198, 117, 105, 161, 21, 241, 23, 84, 32, 62, 155, 245, 172, 30, 78, - 41, 199, 219, 180, 149, 193, 163, 131, 237, 240, 46, 183, 186, 42, 201, 49, 249, 142, 188, - 59, 212, 26, 253, 23, 27, 205, 231, 163, 76, 179, 135, 193, 152, 110, 91, 5, 218, 67, 204, - 164, 128, 183, 221, 82, 16, 72, 249, 111, 118, 182, 24, 249, 91, 215, 215, 155, 2, 0, 0, 0, - 0, 0, 0, 0, 212, 110, 6, 228, 73, 146, 46, 184, 158, 58, 94, 4, 141, 241, 158, 0, 175, 140, - 72, 75, 52, 6, 72, 49, 112, 215, 21, 243, 151, 67, 106, 22, 158, 237, 80, 204, 41, 128, 69, - 52, 154, 189, 124, 203, 35, 107, 132, 241, 234, 31, 3, 165, 87, 58, 10, 92, 252, 227, 214, - 99, 176, 66, 118, 22, 177, 20, 120, 198, 252, 236, 7, 148, 207, 78, 152, 132, 94, 207, 50, - 243, 4, 169, 146, 240, 79, 98, 0, 212, 106, 137, 36, 193, 21, 175, 180, 1, 26, 107, 39, - 198, 89, 152, 26, 220, 138, 105, 243, 45, 63, 106, 163, 80, 74, 253, 176, 207, 47, 52, 7, - 84, 59, 151, 47, 178, 165, 112, 251, 161, - ] - .to_vec(); - let proof_bytes: Vec = [ - 162, 50, 57, 98, 3, 171, 250, 108, 49, 206, 73, 126, 25, 35, 178, 148, 35, 219, 98, 90, - 122, 177, 16, 91, 233, 215, 222, 12, 72, 184, 53, 2, 62, 166, 50, 68, 98, 171, 218, 218, - 151, 177, 133, 223, 129, 53, 114, 236, 181, 215, 223, 91, 102, 225, 52, 122, 122, 206, 36, - 122, 213, 38, 186, 170, 235, 210, 179, 221, 122, 37, 74, 38, 79, 0, 26, 94, 59, 146, 46, - 252, 70, 153, 236, 126, 194, 169, 17, 144, 100, 218, 118, 22, 99, 226, 132, 40, 24, 248, - 232, 197, 195, 220, 254, 52, 36, 248, 18, 167, 167, 206, 108, 29, 120, 188, 18, 78, 86, 8, - 121, 217, 144, 185, 122, 58, 12, 34, 44, 6, 233, 80, 177, 183, 5, 8, 150, 74, 241, 141, 65, - 150, 35, 98, 15, 150, 137, 254, 132, 167, 228, 104, 63, 133, 11, 209, 39, 79, 138, 185, 88, - 20, 242, 102, 69, 73, 243, 88, 29, 91, 127, 157, 82, 192, 52, 95, 143, 49, 227, 83, 19, 26, - 108, 63, 232, 213, 169, 64, 221, 159, 214, 220, 246, 174, 35, 43, 143, 80, 168, 142, 29, - 103, 179, 58, 235, 33, 163, 198, 255, 188, 20, 3, 91, 47, 158, 122, 226, 201, 175, 138, 18, - 24, 178, 219, 78, 12, 96, 10, 2, 133, 35, 230, 149, 235, 206, 1, 177, 211, 245, 168, 74, - 62, 25, 115, 70, 42, 38, 131, 92, 103, 103, 176, 212, 223, 177, 242, 94, 14, - ] - .to_vec(); - let scalar = [ - 232, 255, 255, 239, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, - 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, - ] - .to_vec(); + let _ = committee::signature_aggregation_and_push( + &committee_partial_sigs, + &agg_nonces, + &mut graph, + ); - use ark_bn254::Bn254; - use ark_serialize::CanonicalDeserialize; + let vk_bytes = [ + 115, 158, 251, 51, 106, 255, 102, 248, 22, 171, 229, 158, 80, 192, 240, 217, 99, 162, + 65, 107, 31, 137, 197, 79, 11, 210, 74, 65, 65, 203, 243, 14, 123, 2, 229, 125, 198, + 247, 76, 241, 176, 116, 6, 3, 241, 1, 134, 195, 39, 5, 124, 47, 31, 43, 164, 48, 120, + 207, 150, 125, 108, 100, 48, 155, 137, 132, 16, 193, 139, 74, 179, 131, 42, 119, 25, + 185, 98, 13, 235, 118, 92, 11, 154, 142, 134, 220, 191, 220, 169, 250, 244, 104, 123, + 7, 247, 33, 178, 155, 121, 59, 75, 188, 206, 198, 182, 97, 0, 64, 231, 45, 55, 92, 100, + 17, 56, 159, 79, 13, 219, 221, 33, 39, 193, 24, 36, 58, 105, 8, 70, 206, 176, 209, 146, + 45, 201, 157, 226, 84, 213, 135, 143, 178, 156, 112, 137, 246, 123, 248, 215, 168, 51, + 95, 177, 47, 57, 29, 199, 224, 98, 48, 144, 253, 15, 201, 192, 142, 62, 143, 13, 228, + 89, 51, 58, 6, 226, 139, 99, 207, 22, 113, 215, 79, 91, 158, 166, 210, 28, 90, 218, + 111, 151, 4, 55, 230, 76, 90, 209, 149, 113, 248, 245, 50, 231, 137, 51, 157, 40, 29, + 184, 198, 201, 108, 199, 89, 67, 136, 239, 96, 216, 237, 172, 29, 84, 3, 128, 240, 2, + 218, 169, 217, 118, 179, 34, 226, 19, 227, 59, 193, 131, 108, 20, 113, 46, 170, 196, + 156, 45, 39, 151, 218, 22, 132, 250, 209, 183, 46, 249, 115, 239, 14, 176, 200, 134, + 158, 148, 139, 212, 167, 152, 205, 183, 236, 242, 176, 96, 177, 187, 184, 252, 14, 226, + 127, 127, 173, 147, 224, 220, 8, 29, 63, 73, 215, 92, 161, 110, 20, 154, 131, 23, 217, + 116, 145, 196, 19, 167, 84, 185, 16, 89, 175, 180, 110, 116, 57, 198, 237, 147, 183, + 164, 169, 220, 172, 52, 68, 175, 113, 244, 62, 104, 134, 215, 99, 132, 199, 139, 172, + 108, 143, 25, 238, 201, 128, 85, 24, 73, 30, 186, 142, 186, 201, 79, 3, 176, 185, 70, + 66, 89, 127, 188, 158, 209, 83, 17, 22, 187, 153, 8, 63, 58, 174, 236, 132, 226, 43, + 145, 97, 242, 198, 117, 105, 161, 21, 241, 23, 84, 32, 62, 155, 245, 172, 30, 78, 41, + 199, 219, 180, 149, 193, 163, 131, 237, 240, 46, 183, 186, 42, 201, 49, 249, 142, 188, + 59, 212, 26, 253, 23, 27, 205, 231, 163, 76, 179, 135, 193, 152, 110, 91, 5, 218, 67, + 204, 164, 128, 183, 221, 82, 16, 72, 249, 111, 118, 182, 24, 249, 91, 215, 215, 155, 2, + 0, 0, 0, 0, 0, 0, 0, 212, 110, 6, 228, 73, 146, 46, 184, 158, 58, 94, 4, 141, 241, 158, + 0, 175, 140, 72, 75, 52, 6, 72, 49, 112, 215, 21, 243, 151, 67, 106, 22, 158, 237, 80, + 204, 41, 128, 69, 52, 154, 189, 124, 203, 35, 107, 132, 241, 234, 31, 3, 165, 87, 58, + 10, 92, 252, 227, 214, 99, 176, 66, 118, 22, 177, 20, 120, 198, 252, 236, 7, 148, 207, + 78, 152, 132, 94, 207, 50, 243, 4, 169, 146, 240, 79, 98, 0, 212, 106, 137, 36, 193, + 21, 175, 180, 1, 26, 107, 39, 198, 89, 152, 26, 220, 138, 105, 243, 45, 63, 106, 163, + 80, 74, 253, 176, 207, 47, 52, 7, 84, 59, 151, 47, 178, 165, 112, 251, 161, + ] + .to_vec(); + let proof_bytes: Vec = [ + 162, 50, 57, 98, 3, 171, 250, 108, 49, 206, 73, 126, 25, 35, 178, 148, 35, 219, 98, 90, + 122, 177, 16, 91, 233, 215, 222, 12, 72, 184, 53, 2, 62, 166, 50, 68, 98, 171, 218, + 218, 151, 177, 133, 223, 129, 53, 114, 236, 181, 215, 223, 91, 102, 225, 52, 122, 122, + 206, 36, 122, 213, 38, 186, 170, 235, 210, 179, 221, 122, 37, 74, 38, 79, 0, 26, 94, + 59, 146, 46, 252, 70, 153, 236, 126, 194, 169, 17, 144, 100, 218, 118, 22, 99, 226, + 132, 40, 24, 248, 232, 197, 195, 220, 254, 52, 36, 248, 18, 167, 167, 206, 108, 29, + 120, 188, 18, 78, 86, 8, 121, 217, 144, 185, 122, 58, 12, 34, 44, 6, 233, 80, 177, 183, + 5, 8, 150, 74, 241, 141, 65, 150, 35, 98, 15, 150, 137, 254, 132, 167, 228, 104, 63, + 133, 11, 209, 39, 79, 138, 185, 88, 20, 242, 102, 69, 73, 243, 88, 29, 91, 127, 157, + 82, 192, 52, 95, 143, 49, 227, 83, 19, 26, 108, 63, 232, 213, 169, 64, 221, 159, 214, + 220, 246, 174, 35, 43, 143, 80, 168, 142, 29, 103, 179, 58, 235, 33, 163, 198, 255, + 188, 20, 3, 91, 47, 158, 122, 226, 201, 175, 138, 18, 24, 178, 219, 78, 12, 96, 10, 2, + 133, 35, 230, 149, 235, 206, 1, 177, 211, 245, 168, 74, 62, 25, 115, 70, 42, 38, 131, + 92, 103, 103, 176, 212, 223, 177, 242, 94, 14, + ] + .to_vec(); + let scalar = [ + 232, 255, 255, 239, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, + 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, + ] + .to_vec(); - let proof: ark_groth16::Proof = - ark_groth16::Proof::deserialize_uncompressed(&proof_bytes[..]).unwrap(); - let vk: ark_groth16::VerifyingKey = - ark_groth16::VerifyingKey::deserialize_uncompressed(&vk_bytes[..]).unwrap(); - let scalar: ark_bn254::Fr = ark_bn254::Fr::deserialize_uncompressed(&scalar[..]).unwrap(); - let scalars = vec![scalar]; + use ark_bn254::Bn254; + use ark_serialize::CanonicalDeserialize; - let proof_sigs = operator::sign_proof(&vk, proof, scalars, &operator_wots_seckeys); + let proof: ark_groth16::Proof = + ark_groth16::Proof::deserialize_uncompressed(&proof_bytes[..]).unwrap(); + let vk: ark_groth16::VerifyingKey = + ark_groth16::VerifyingKey::deserialize_uncompressed(&vk_bytes[..]).unwrap(); + let scalar: ark_bn254::Fr = ark_bn254::Fr::deserialize_uncompressed(&scalar[..]).unwrap(); + let scalars = vec![scalar]; - let (_, commit_txns, _) = operator::operator_sign_assert( - operator_keypair, - &mut graph, - &operator_wots_pubkeys, - proof_sigs.clone(), - ) - .unwrap(); - let extracted_proof_sigs = - verifier::extract_proof_sigs_from_assert_commit_txns(commit_txns).unwrap(); + let proof_sigs = operator::sign_proof(&vk, proof, scalars, &operator_wots_seckeys); + + let (_, commit_txns, _) = operator::operator_sign_assert( + operator_keypair, + &mut graph, + &operator_wots_pubkeys, + proof_sigs.clone(), + ) + .unwrap(); + let extracted_proof_sigs = + verifier::extract_proof_sigs_from_assert_commit_txns(commit_txns).unwrap(); - assert_eq!(proof_sigs, extracted_proof_sigs); + assert_eq!(proof_sigs, extracted_proof_sigs); + } } diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 551b4f9e..5436ef3a 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -15,3 +15,6 @@ esplora-client = { workspace = true } anyhow = { workspace = true } store = { workspace = true } + +[dev-dependencies] +tempfile = "3.19.1" diff --git a/crates/client/src/chain/goat_adaptor.rs b/crates/client/src/chain/goat_adaptor.rs index 2dc0f9d5..288ed171 100644 --- a/crates/client/src/chain/goat_adaptor.rs +++ b/crates/client/src/chain/goat_adaptor.rs @@ -19,7 +19,6 @@ use alloy::{ }; use anyhow::format_err; use async_trait::async_trait; -use dotenv; use std::str::FromStr; use uuid::Uuid; @@ -153,7 +152,7 @@ impl GoatAdaptor { // send tx let pending_tx = self.provider.send_raw_transaction(signed_tx.encoded_2718().as_slice()).await?; - Ok(pending_tx.tx_hash().clone()) + Ok(*pending_tx.tx_hash()) } } @@ -325,7 +324,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result<()> { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); let tx_request: TransactionRequest = self .gate_way .postPeginData( @@ -370,9 +369,9 @@ impl ChainAdaptor for GoatAdaptor { operator_datas: &[OperatorData], ) -> anyhow::Result<()> { let graph_ids = - graph_ids.into_iter().map(|v| FixedBytes::<16>::from_slice(&v.into_bytes())).collect(); + graph_ids.iter().map(|v| FixedBytes::<16>::from_slice(&v.into_bytes())).collect(); let operator_datas: Vec = - operator_datas.into_iter().map(|v| (*v).clone().into()).collect(); + operator_datas.iter().map(|v| (*v).clone().into()).collect(); let tx_request = self .gate_way .postOperatorDataBatch( @@ -422,7 +421,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result<()> { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); let tx_request = self .gate_way .proceedWithdraw( @@ -448,7 +447,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result<()> { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); let tx_request = self .gate_way .finishWithdrawHappyPath( @@ -474,7 +473,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result<()> { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); let tx_request = self .gate_way .finishWithdrawUnhappyPath( @@ -500,7 +499,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result<()> { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); let tx_request = self .gate_way .finishWithdrawDisproved( @@ -525,7 +524,7 @@ impl ChainAdaptor for GoatAdaptor { index: u64, ) -> anyhow::Result { let proof: Vec> = - proof.into_iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); + proof.iter().map(|v| FixedBytes::<32>::from_slice(v)).collect(); Ok(self .gate_way .verifyMerkleProof( @@ -556,7 +555,7 @@ impl GoatAdaptor { }; let provider = ProviderBuilder::new().on_http(config.rpc_url); Self { - gateway_address: config.gateway_address.clone(), + gateway_address: config.gateway_address, gateway_creation_block: config.gateway_creation_block, provider: provider.clone(), to_block: config.to_block, diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 9f7b20c3..342ff458 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1,6 +1,6 @@ use crate::chain::chain::Chain; use crate::chain::chain_adaptor::{ - ChainAdaptor, GoatNetwork, OperatorData, PeginData, WithdrawData, get_chain_adaptor, + ChainAdaptor, GoatNetwork, OperatorData, PeginData, get_chain_adaptor, }; use crate::chain::goat_adaptor::GoatInitConfig; use crate::esplora::get_esplora_url; @@ -22,7 +22,7 @@ pub struct BitVM2Client { impl BitVM2Client { #[allow(clippy::too_many_arguments)] pub async fn new( - db_path: String, + db_path: &str, esplora_url: Option<&str>, btc_network: Network, goat_network: GoatNetwork, @@ -42,11 +42,11 @@ impl BitVM2Client { pub async fn fetch_btc_block(&self, block_height: u32) -> anyhow::Result { let block_hash = self.esplora.get_block_hash(block_height).await?; - Ok(self.esplora.get_block_by_hash(&block_hash).await?.ok_or(anyhow::format_err!( + self.esplora.get_block_by_hash(&block_hash).await?.ok_or(anyhow::format_err!( "failed to fetch block at :{} hash:{}", block_height, block_hash.to_string() - ))?) + )) } pub async fn fetch_btc_address_utxos(&self, address: BtcAddress) -> anyhow::Result> { diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 1055ef42..3559e997 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -24,8 +24,9 @@ mod tests { chain_id: 48816_u32, }; // let local_db = LocalDB::new(&format!("sqlite:{db_path}"), true).await; + let tmp_db = tempfile::NamedTempFile::new().unwrap(); let client = BitVM2Client::new( - "/tmp/.bitvm2-node.db".to_string(), + tmp_db.path().as_os_str().to_str().unwrap(), None, Network::Testnet, GoatNetwork::Test, diff --git a/crates/identity/src/musig2.rs b/crates/identity/src/musig2.rs index 9032fe4b..0f608652 100644 --- a/crates/identity/src/musig2.rs +++ b/crates/identity/src/musig2.rs @@ -1,31 +1,16 @@ -use futures::SinkExt; use rand::RngCore; -use secp256k1::{Message, Secp256k1, SecretKey}; +use secp256k1::{Secp256k1, SecretKey}; use std::string::String; -use std::{ - error::Error, - net::{Ipv4Addr, Ipv6Addr}, -}; -use tokio::sync::mpsc::{self, Receiver, Sender}; -use libp2p::{ - core::{Multiaddr, multiaddr::Protocol}, - identify, identity, noise, - swarm::{NetworkBehaviour, SwarmEvent}, - tcp, yamux, -}; use musig2::KeyAggContext; use musig2::k256::PublicKey; -use musig2::secp::Scalar; use musig2::{ - AggNonce, CompactSignature, FirstRound, PartialSignature, PubNonce, SecNonce, SecNonceSpices, - SecondRound, + CompactSignature, FirstRound, PartialSignature, PubNonce, SecNonceSpices, SecondRound, }; use std::collections::HashMap; use std::sync::Arc; use std::sync::LazyLock; use std::sync::Mutex; -use tracing_subscriber::EnvFilter; pub static MSG_QUEUE: LazyLock>>> = LazyLock::new(|| Arc::new(Mutex::new(HashMap::new()))); @@ -55,7 +40,7 @@ impl MuSig2StateMachine { let mut nonce_seed = [0u8; 32]; rand::rngs::OsRng.fill_bytes(&mut nonce_seed); - let mut first_round = FirstRound::new( + let first_round = FirstRound::new( ctx.clone(), nonce_seed, signer_index, @@ -85,7 +70,7 @@ impl MuSig2StateMachine { pub fn second_round_send(&mut self) -> PartialSignature { let first_round = self.first_round.take().unwrap(); - let mut second_round: SecondRound = + let second_round: SecondRound = first_round.finalize(self.secret_key.take().unwrap(), self.message.clone()).unwrap(); self.second_round = Some(second_round); @@ -134,7 +119,7 @@ pub mod tests { .enumerate() .map(|(idx, s)| { MuSig2StateMachine::new( - s.secret_key().clone(), + s.secret_key(), topic.clone(), message.clone(), idx, @@ -178,7 +163,7 @@ pub mod tests { let mut is_complete = false; for (i, v) in second_round.iter().enumerate() { if i != idx { - is_complete = s.second_round_receive(i, v.clone()); + is_complete = s.second_round_receive(i, *v); } } is_complete diff --git a/crates/spv/src/header_chain.rs b/crates/spv/src/header_chain.rs index 79702646..c1d980fc 100644 --- a/crates/spv/src/header_chain.rs +++ b/crates/spv/src/header_chain.rs @@ -20,17 +20,16 @@ pub struct CircuitBlockHeader { impl CircuitBlockHeader { pub fn compute_block_hash(&self) -> [u8; 32] { let mut hasher = Sha256::new(); - hasher.update(&self.version.to_le_bytes()); - hasher.update(&self.prev_block_hash); - hasher.update(&self.merkle_root); - hasher.update(&self.time.to_le_bytes()); - hasher.update(&self.bits.to_le_bytes()); - hasher.update(&self.nonce.to_le_bytes()); + hasher.update(self.version.to_le_bytes()); + hasher.update(self.prev_block_hash); + hasher.update(self.merkle_root); + hasher.update(self.time.to_le_bytes()); + hasher.update(self.bits.to_le_bytes()); + hasher.update(self.nonce.to_le_bytes()); let first_hash_result = hasher.finalize_reset(); hasher.update(first_hash_result); - let result: [u8; 32] = - hasher.finalize().try_into().expect("SHA256 should produce a 32-byte output"); + let result: [u8; 32] = hasher.finalize().into(); result } } @@ -48,17 +47,17 @@ impl From
for CircuitBlockHeader { } } -impl Into
for CircuitBlockHeader { - fn into(self) -> Header { +impl From for Header { + fn from(val: CircuitBlockHeader) -> Self { Header { - version: Version::from_consensus(self.version), - prev_blockhash: BlockHash::from_slice(&self.prev_block_hash) + version: Version::from_consensus(val.version), + prev_blockhash: BlockHash::from_slice(&val.prev_block_hash) .expect("Previous block hash is 32 bytes"), - merkle_root: TxMerkleNode::from_slice(&self.merkle_root) + merkle_root: TxMerkleNode::from_slice(&val.merkle_root) .expect("Merkle root is 32 bytes"), - time: self.time, - bits: CompactTarget::from_consensus(self.bits), - nonce: self.nonce, + time: val.time, + bits: CompactTarget::from_consensus(val.bits), + nonce: val.nonce, } } } diff --git a/crates/spv/src/lib.rs b/crates/spv/src/lib.rs index 09cfb3cb..909341c3 100644 --- a/crates/spv/src/lib.rs +++ b/crates/spv/src/lib.rs @@ -161,7 +161,7 @@ mod tests { .iter() .map(|tx| { println!("{:?}", tx); - CircuitTransaction(bitcoin::consensus::deserialize(*tx).unwrap()) + CircuitTransaction(bitcoin::consensus::deserialize(tx).unwrap()) }) .collect::>(); let mut bitcoin_merkle_proofs: Vec = vec![]; diff --git a/crates/spv/src/merkle_tree.rs b/crates/spv/src/merkle_tree.rs index 12210a59..7fed80ee 100644 --- a/crates/spv/src/merkle_tree.rs +++ b/crates/spv/src/merkle_tree.rs @@ -48,7 +48,7 @@ impl BitcoinMerkleTree { tree.nodes[curr_level_offset].push(combined_hash); } curr_level_offset += 1; - prev_level_size = (prev_level_size + 1) / 2; + prev_level_size = prev_level_size.div_ceil(2); prev_level_index_offset = 0; } tree diff --git a/crates/spv/src/mmr.rs b/crates/spv/src/mmr.rs index 7a9e0c19..de00d63a 100644 --- a/crates/spv/src/mmr.rs +++ b/crates/spv/src/mmr.rs @@ -12,6 +12,12 @@ pub struct MMRHost { pub nodes: Vec>, } +impl Default for MMRHost { + fn default() -> Self { + Self::new() + } +} + impl MMRHost { /// Creates a new MMR for native usage. pub fn new() -> Self { @@ -58,7 +64,7 @@ impl MMRHost { /// Generates a proof for a given index. Returns the leaf as well. pub fn generate_proof(&self, index: u32) -> ([u8; 32], MMRInclusionProof) { - if self.nodes[0].len() == 0 { + if self.nodes[0].is_empty() { panic!("MMR is empty"); } if self.nodes[0].len() <= index as usize { @@ -74,7 +80,7 @@ impl MMRHost { let sibling_index = if current_index % 2 == 0 { current_index + 1 } else { current_index - 1 }; proof.push(self.nodes[current_level][sibling_index as usize]); - current_index = current_index / 2; + current_index /= 2; current_level += 1; } let (subroot_idx, internal_idx) = self.get_helpers_from_index(index); @@ -143,6 +149,12 @@ pub struct MMRGuest { pub size: u32, } +impl Default for MMRGuest { + fn default() -> Self { + Self::new() + } +} + impl MMRGuest { /// Creates a new MMR for inside zkVM pub fn new() -> Self { @@ -180,10 +192,9 @@ impl MMRGuest { } } +#[cfg(test)] mod tests { - use super::*; - #[test] #[should_panic(expected = "MMR is empty")] fn test_mmr_native_fail_0() { diff --git a/crates/spv/src/transaction.rs b/crates/spv/src/transaction.rs index aba48103..b8a2890d 100644 --- a/crates/spv/src/transaction.rs +++ b/crates/spv/src/transaction.rs @@ -121,9 +121,9 @@ impl From for CircuitTransaction { } } -impl Into for CircuitTransaction { - fn into(self) -> Transaction { - self.0 +impl From for Transaction { + fn from(val: CircuitTransaction) -> Self { + val.0 } } diff --git a/crates/store/src/ipfs.rs b/crates/store/src/ipfs.rs index 34060208..c18a72ed 100644 --- a/crates/store/src/ipfs.rs +++ b/crates/store/src/ipfs.rs @@ -59,7 +59,7 @@ async fn collect_files(base_path: &Path) -> Result
{ let file = File::open(entry.path()).await?; let stream = FramedRead::new(file, BytesCodec::new()) .map_ok(|b| b.freeze()) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)); + .map_err(std::io::Error::other); let body = reqwest::Body::wrap_stream(stream); let part = Part::stream(body).file_name(rel_path.clone()); form = form.part("file", part); @@ -129,7 +129,7 @@ impl IPFS { #[cfg(test)] pub mod tests { use super::*; - use std::io::Write; + #[tokio::test] async fn test_ipfs_add_and_get() { println!("connecting to localhost:5001..."); diff --git a/crates/store/src/localdb.rs b/crates/store/src/localdb.rs index 616c7dff..3026b7c9 100644 --- a/crates/store/src/localdb.rs +++ b/crates/store/src/localdb.rs @@ -4,7 +4,6 @@ use crate::{ COMMITTEE_PRE_SIGN_NUM, GrapRpcQueryData, Graph, Instance, Message, Node, NodesOverview, NonceCollect, NonceCollectMetaData, PubKeyCollect, PubKeyCollectMetaData, }; -use futures::future::ok; use sqlx::migrate::Migrator; use sqlx::pool::PoolConnection; use sqlx::types::Uuid; @@ -487,7 +486,7 @@ impl<'a> StorageProcessor<'a> { let query_str = format!( "Update message Set state = {} WHERE id IN ({})", state, - create_place_holders(&ids) + create_place_holders(ids) ); let mut query = sqlx::query(&query_str); for id in ids { @@ -528,14 +527,14 @@ impl<'a> StorageProcessor<'a> { pub async fn store_pubkeys( &mut self, instance_id: Uuid, - pubkeys: &Vec, + pubkeys: &[String], ) -> anyhow::Result<()> { let pubkey_collect = sqlx::query_as!( PubKeyCollect , "SELECT instance_id as \"instance_id:Uuid\", pubkeys, created_at, updated_at FROM pubkey_collect WHERE instance_id = ?", instance_id).fetch_optional(self.conn()).await?; - let mut pubkeys = pubkeys.clone(); + let mut pubkeys = pubkeys.to_owned(); let mut created_at = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; let updated_at = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; if let Some(pubkey_collect) = pubkey_collect { @@ -581,9 +580,9 @@ impl<'a> StorageProcessor<'a> { &mut self, instance_id: Uuid, graph_id: Uuid, - nonces: &Vec<[String; COMMITTEE_PRE_SIGN_NUM]>, + nonces: &[[String; COMMITTEE_PRE_SIGN_NUM]], committee_pubkey: String, - partial_sigs: &Vec, + partial_sigs: &[String], ) -> anyhow::Result<()> { let nonce_collect = sqlx::query_as!( NonceCollect , @@ -591,8 +590,8 @@ impl<'a> StorageProcessor<'a> { partial_sigs, created_at, updated_at FROM nonce_collect WHERE instance_id = ? AND graph_id = ?", instance_id, graph_id).fetch_optional(self.conn()).await?; - let mut nonces = nonces.clone(); - let mut partial_sigs = partial_sigs.clone(); + let mut nonces = nonces.to_owned(); + let mut partial_sigs = partial_sigs.to_owned(); let mut created_at = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; let updated_at = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; if let Some(nonce_collect) = nonce_collect { diff --git a/node/Cargo.toml b/node/Cargo.toml index 31107d04..39a5e35a 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -78,3 +78,4 @@ bitcoin-script = { workspace = true } once_cell = { workspace = true } [dev-dependencies] +tempfile = "3.19.1" diff --git a/node/src/action.rs b/node/src/action.rs index a823393a..565809f1 100644 --- a/node/src/action.rs +++ b/node/src/action.rs @@ -206,7 +206,7 @@ pub mod statics { OPERATOR_CURRENT_GRAPH.lock().unwrap().is_some() } pub fn current_processing_graph() -> Option<(Uuid, Uuid)> { - OPERATOR_CURRENT_GRAPH.lock().unwrap().clone() + *OPERATOR_CURRENT_GRAPH.lock().unwrap() } pub fn force_stop_current_graph() { *OPERATOR_CURRENT_GRAPH.lock().unwrap() = None; @@ -232,7 +232,6 @@ pub mod todo_funcs { use std::fs::{self, File}; use std::io::{BufReader, BufWriter}; use std::path::Path; - use store::GraphStatus; /// Database related pub async fn store_committee_pubkeys( @@ -638,7 +637,7 @@ pub mod todo_funcs { let node_address = node_p2wsh_address(get_network(), &get_node_pubkey()?); let utxos = client.esplora.get_address_utxo(node_address).await?; let utxo_spent_fee = Amount::from_sat( - (get_fee_rate(&client).await? * 2.0 * CHEKSIG_P2WSH_INPUT_VBYTES as f64).ceil() as u64, + (get_fee_rate(client).await? * 2.0 * CHEKSIG_P2WSH_INPUT_VBYTES as f64).ceil() as u64, ); let total_effective_balance: Amount = utxos.iter().map(|utxo| utxo.value - utxo_spent_fee).sum(); @@ -757,7 +756,7 @@ pub async fn recv_and_dispatch( // TODO return Ok(()); } - let message: GOATMessage = serde_json::from_slice(&message)?; + let message: GOATMessage = serde_json::from_slice(message)?; println!("Received message: {:?}", message); if message.actor != actor && message.actor != Actor::All && actor != Actor::Relayer { return Ok(()); @@ -944,8 +943,7 @@ pub async fn recv_and_dispatch( } } let mut graph = - get_graph(&&client, receive_data.instance_id, receive_data.graph_id) - .await?; + get_graph(&client, receive_data.instance_id, receive_data.graph_id).await?; signature_aggregation_and_push( &grouped_partial_sigs, &receive_data.agg_nonces, @@ -1063,30 +1061,29 @@ pub async fn recv_and_dispatch( (GOATMessageContent::Take1Ready(receive_data), Actor::Operator) => { let mut graph = get_graph(&client, receive_data.instance_id, receive_data.graph_id).await?; - if graph.parameters.operator_pubkey == env::get_node_pubkey()? { - if todo_funcs::is_take1_timelock_expired(&client, graph.take1.tx().compute_txid()) + if graph.parameters.operator_pubkey == env::get_node_pubkey()? + && todo_funcs::is_take1_timelock_expired(&client, graph.take1.tx().compute_txid()) .await? - { - let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); - let keypair = master_key.keypair_for_graph(receive_data.graph_id); - let take1_tx = operator_sign_take1(keypair, &mut graph)?; - let take1_txid = take1_tx.compute_txid(); - todo_funcs::broadcast_tx(&client, &take1_tx).await?; - let message_content = GOATMessageContent::Take1Sent(Take1Sent { - instance_id: receive_data.instance_id, - graph_id: receive_data.graph_id, - take1_txid, - }); - send_to_peer(swarm, GOATMessage::from_typed(Actor::All, &message_content)?)?; - update_graph_status_or_ipfs_base( - &client, - receive_data.graph_id, - None, - Some(GraphStatus::Take1.to_string()), - ) - .await?; - // NOTE: clean up other graphs? - } + { + let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); + let keypair = master_key.keypair_for_graph(receive_data.graph_id); + let take1_tx = operator_sign_take1(keypair, &mut graph)?; + let take1_txid = take1_tx.compute_txid(); + todo_funcs::broadcast_tx(&client, &take1_tx).await?; + let message_content = GOATMessageContent::Take1Sent(Take1Sent { + instance_id: receive_data.instance_id, + graph_id: receive_data.graph_id, + take1_txid, + }); + send_to_peer(swarm, GOATMessage::from_typed(Actor::All, &message_content)?)?; + update_graph_status_or_ipfs_base( + &client, + receive_data.graph_id, + None, + Some(GraphStatus::Take1.to_string()), + ) + .await?; + // NOTE: clean up other graphs? } } // ChallengeSent sent by challenger @@ -1094,78 +1091,69 @@ pub async fn recv_and_dispatch( (GOATMessageContent::ChallengeSent(receive_data), Actor::Operator) => { let mut graph = get_graph(&client, receive_data.instance_id, receive_data.graph_id).await?; - if graph.parameters.operator_pubkey == env::get_node_pubkey()? { - if todo_funcs::validate_challenge( + if graph.parameters.operator_pubkey == env::get_node_pubkey()? + && todo_funcs::validate_challenge( &client, &graph.kickoff.tx().compute_txid(), &receive_data.challenge_txid, ) .await? - { - let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); - let keypair = master_key.keypair_for_graph(receive_data.graph_id); - let (operator_wots_seckeys, operator_wots_pubkeys) = - master_key.wots_keypair_for_graph(receive_data.graph_id); - let (proof, pubin, vk) = todo_funcs::get_groth16_proof( - receive_data.instance_id, - receive_data.graph_id, - )?; - let proof_sigs = sign_proof(&vk, proof, pubin, &operator_wots_seckeys); - let (assert_init_tx, assert_commit_txns, assert_final_tx) = - operator_sign_assert( - keypair, - &mut graph, - &operator_wots_pubkeys, - proof_sigs, - )?; - todo_funcs::broadcast_tx(&client, &assert_init_tx).await?; - for tx in assert_commit_txns { - todo_funcs::broadcast_tx(&client, &tx).await?; - } - todo_funcs::broadcast_tx(&client, &assert_final_tx).await?; - update_graph_status_or_ipfs_base( - &client, - receive_data.graph_id, - None, - Some(GraphStatus::Assert.to_string()), - ) - .await?; - // malicious Operator may not broadcast assert to the p2p network - // Relayer will monitor all graphs & broadcast AssertSent + { + let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); + let keypair = master_key.keypair_for_graph(receive_data.graph_id); + let (operator_wots_seckeys, operator_wots_pubkeys) = + master_key.wots_keypair_for_graph(receive_data.graph_id); + let (proof, pubin, vk) = + todo_funcs::get_groth16_proof(receive_data.instance_id, receive_data.graph_id)?; + let proof_sigs = sign_proof(&vk, proof, pubin, &operator_wots_seckeys); + let (assert_init_tx, assert_commit_txns, assert_final_tx) = + operator_sign_assert(keypair, &mut graph, &operator_wots_pubkeys, proof_sigs)?; + todo_funcs::broadcast_tx(&client, &assert_init_tx).await?; + for tx in assert_commit_txns { + todo_funcs::broadcast_tx(&client, &tx).await?; } + todo_funcs::broadcast_tx(&client, &assert_final_tx).await?; + update_graph_status_or_ipfs_base( + &client, + receive_data.graph_id, + None, + Some(GraphStatus::Assert.to_string()), + ) + .await?; + // malicious Operator may not broadcast assert to the p2p network + // Relayer will monitor all graphs & broadcast AssertSent } } // Take2Ready sent by relayer (GOATMessageContent::Take2Ready(receive_data), Actor::Operator) => { let mut graph = get_graph(&client, receive_data.instance_id, receive_data.graph_id).await?; - if graph.parameters.operator_pubkey == env::get_node_pubkey()? { - if todo_funcs::is_take2_timelock_expired( + if graph.parameters.operator_pubkey == env::get_node_pubkey()? + && todo_funcs::is_take2_timelock_expired( &client, graph.assert_final.tx().compute_txid(), ) .await? - { - let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); - let keypair = master_key.keypair_for_graph(receive_data.graph_id); - let take2_tx = operator_sign_take2(keypair, &mut graph)?; - let take2_txid = take2_tx.compute_txid(); - todo_funcs::broadcast_tx(&client, &take2_tx).await?; - let message_content = GOATMessageContent::Take2Sent(Take2Sent { - instance_id: receive_data.instance_id, - graph_id: receive_data.graph_id, - take2_txid, - }); - send_to_peer(swarm, GOATMessage::from_typed(Actor::All, &message_content)?)?; - update_graph_status_or_ipfs_base( - &client, - receive_data.graph_id, - None, - Some(GraphStatus::Take2.to_string()), - ) - .await?; - // NOTE: clean up other graphs? - } + { + let master_key = OperatorMasterKey::new(env::get_bitvm_key()?); + let keypair = master_key.keypair_for_graph(receive_data.graph_id); + let take2_tx = operator_sign_take2(keypair, &mut graph)?; + let take2_txid = take2_tx.compute_txid(); + todo_funcs::broadcast_tx(&client, &take2_tx).await?; + let message_content = GOATMessageContent::Take2Sent(Take2Sent { + instance_id: receive_data.instance_id, + graph_id: receive_data.graph_id, + take2_txid, + }); + send_to_peer(swarm, GOATMessage::from_typed(Actor::All, &message_content)?)?; + update_graph_status_or_ipfs_base( + &client, + receive_data.graph_id, + None, + Some(GraphStatus::Take2.to_string()), + ) + .await?; + // NOTE: clean up other graphs? } } // AssertSent sent by relayer @@ -1368,7 +1356,7 @@ where let client = reqwest::Client::new(); let url = reqwest::Url::parse(&format!("{addr}/{uri}"))?; - let mut req = Request::new(method, url); + let req = Request::new(method, url); let req_builder = reqwest::RequestBuilder::from_parts(client, req); let resp = req_builder.json(¶ms).send().await?; let txt = resp.text().await?; @@ -1389,13 +1377,7 @@ pub async fn store_committee_pub_nonces( format!("length wrong: expect {}, real {}", COMMITTEE_PRE_SIGN_NUM, v.len()) })?; Ok(storage_process - .store_nonces( - instance_id, - graph_id, - &vec![nonces_arr], - committee_pubkey.to_string(), - &vec![], - ) + .store_nonces(instance_id, graph_id, &[nonces_arr], committee_pubkey.to_string(), &[]) .await?) } pub async fn get_committee_pub_nonces( @@ -1451,7 +1433,7 @@ pub async fn store_committee_partial_sigs( let signs: Vec = partial_sigs.iter().map(|v| hex::encode(v.serialize())).collect(); Ok(storage_process - .store_nonces(instance_id, graph_id, &vec![], committee_pubkey.to_string(), &signs) + .store_nonces(instance_id, graph_id, &[], committee_pubkey.to_string(), &signs) .await?) } @@ -1547,15 +1529,13 @@ pub async fn get_graph( if graph.instance_id.ne(&instance_id) { return Err(format!( "grap with graph_id:{} has instance_id:{} not match expec instance:{}", - graph_id.to_string(), - graph.instance_id.to_string(), - instance_id.to_string() + graph_id, graph.instance_id, instance_id ) .into()); } if graph.raw_data.is_none() { - return Err(format!("grap with graph_id:{} raw data is none", graph_id.to_string()).into()); + return Err(format!("grap with graph_id:{} raw data is none", graph_id).into()); } let res: Bitvm2Graph = serde_json::from_str(graph.raw_data.unwrap().as_str())?; Ok(res) diff --git a/node/src/bitcoin/checker.rs b/node/src/bitcoin/checker.rs index f4735b62..1a8d8a6c 100644 --- a/node/src/bitcoin/checker.rs +++ b/node/src/bitcoin/checker.rs @@ -1,14 +1,10 @@ use anyhow::{Result, bail}; -use bitcoin::blockdata::script::Script; use bitcoin::hashes::Hash; use bitcoin::{Amount, Block, Network, Transaction, Txid}; -use esplora_client::{AsyncClient, Builder, Tx}; -use futures::{StreamExt, stream}; +use esplora_client::AsyncClient; +use futures::StreamExt; use spv::verify_merkle_proof; -use spv::{ - BitcoinMerkleTree, BlockInclusionProof, CircuitBlockHeader, CircuitTransaction, MMRGuest, - MMRHost, SPV, -}; +use spv::{BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, MMRGuest, MMRHost, SPV}; /// Fetch block at specific height pub async fn fetch_block(cli: &AsyncClient, block_hei: u32) -> Result { @@ -70,7 +66,7 @@ pub async fn check_pegin_tx( let mut mmr_guest = MMRGuest::new(); let block_headers = blocks .iter() - .map(|b| CircuitBlockHeader::from(b.header.clone())) + .map(|b| CircuitBlockHeader::from(b.header)) .collect::>(); let target_txid: Txid = pegin_txid.parse()?; @@ -104,7 +100,7 @@ pub async fn check_pegin_tx( bail!("Can not verify tx merkle proof"); } - let bitcoin_merkle_proofs = vec![bitcoin_merkle_proof]; + let bitcoin_merkle_proofs = [bitcoin_merkle_proof]; mmr_native.append(target_block_header.compute_block_hash()); mmr_guest.append(target_block_header.compute_block_hash()); @@ -140,8 +136,9 @@ pub async fn check_pegin_tx( } #[cfg(test)] -pub mod test { +mod tests { use super::*; + use esplora_client::Builder; use futures::{StreamExt, stream}; #[tokio::test] async fn test_check_pegin_tx() { @@ -153,7 +150,7 @@ pub mod test { let block_height_start = 4296464; let block_height = block_height_start + 1; - let blocks = stream::iter((block_height_start..block_height).into_iter()) + let blocks = stream::iter((block_height_start..block_height)) .then(|x| { let value = client.clone(); async move { fetch_block(&value, x).await.unwrap() } diff --git a/node/src/env.rs b/node/src/env.rs index cce98706..cfb916df 100644 --- a/node/src/env.rs +++ b/node/src/env.rs @@ -57,18 +57,18 @@ pub fn get_committee_member_num() -> usize { pub fn get_bitvm2_client_config() -> GoatInitConfig { let rpc_url_str = std::env::var(ENV_GOAT_CHAIN_URL) - .expect(format!("Failed to read {} variable", ENV_GOAT_CHAIN_URL).as_str()); - let gateway_address_str = std::env::var(ENV_GOAT_GATEWAY_CONTRACT_ADDRESS) - .expect(format!("Failed to read {} variable", ENV_GOAT_GATEWAY_CONTRACT_ADDRESS).as_str()); - let gateway_creation = std::env::var(ENV_GOAT_GATEWAY_CONTRACT_CREATION) - .expect(format!("Failed to read {} variable", ENV_GOAT_GATEWAY_CONTRACT_CREATION).as_str()); + .unwrap_or_else(|_| panic!("Failed to read {} variable", ENV_GOAT_CHAIN_URL)); + let gateway_address_str = + std::env::var(ENV_GOAT_GATEWAY_CONTRACT_ADDRESS).unwrap_or_else(|_| { + panic!("Failed to read {} variable", ENV_GOAT_GATEWAY_CONTRACT_ADDRESS) + }); + let gateway_creation = std::env::var(ENV_GOAT_GATEWAY_CONTRACT_CREATION).unwrap_or_else(|_| { + panic!("Failed to read {} variable", ENV_GOAT_GATEWAY_CONTRACT_CREATION) + }); let to_block = std::env::var(ENV_GOAT_GATEWAY_CONTRACT_TO_BLOCK); - let private_key = match std::env::var(ENV_GOAT_PRIVATE_KEY) { - Ok(key) => Some(key), - Err(_) => None, - }; + let private_key = std::env::var(ENV_GOAT_PRIVATE_KEY).ok(); let chain_id = std::env::var(ENV_GOAT_CHAIN_ID) - .expect(format!("Failed to read {} variable", ENV_GOAT_CHAIN_ID).as_str()); + .unwrap_or_else(|_| panic!("Failed to read {} variable", ENV_GOAT_CHAIN_ID)); let rpc_url = rpc_url_str.parse::(); let gateway_address = gateway_address_str.parse::(); diff --git a/node/src/main.rs b/node/src/main.rs index bbc8e607..fd16b252 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -2,39 +2,20 @@ use base64::Engine; use clap::{Parser, Subcommand, command}; use libp2p::PeerId; -use libp2p::bytes::BufMut; use libp2p::futures::StreamExt; -use libp2p::identity::Keypair; -use libp2p::{ - gossipsub, kad, mdns, - multiaddr::{Multiaddr, Protocol}, - noise, - swarm::{NetworkBehaviour, SwarmEvent}, - tcp, yamux, -}; -use libp2p_metrics::{Metrics, Registry}; +use libp2p::{gossipsub, kad, mdns, multiaddr::Protocol, noise, swarm::SwarmEvent, tcp, yamux}; +use libp2p_metrics::Registry; use std::collections::HashMap; -use std::io::{Read, Write}; -use std::ops::Add; use std::str::FromStr; use std::sync::{Arc, Mutex}; -use std::thread::LocalKey; -use std::{ - error::Error, - net::Ipv4Addr, - time::{Duration, Instant}, -}; +use std::{error::Error, net::Ipv4Addr, time::Duration}; use tokio::{io, io::AsyncBufReadExt, select}; -use opentelemetry::{KeyValue, trace::TracerProvider as _}; -use opentelemetry_sdk::{runtime, trace::TracerProvider}; -use tracing::log::__private_api::loc; -use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt}; +use tracing_subscriber::{EnvFilter, Layer, util::SubscriberInitExt}; use zeroize::Zeroizing; use bitvm2_lib::actors::Actor; -use identity; mod action; mod bitcoin; @@ -45,8 +26,7 @@ mod rpc_service; use crate::action::GOATMessage; use crate::middleware::behaviour::AllBehavioursEvent; -use anyhow::{Result, bail}; -use libp2p::gossipsub::{MessageId, Topic}; +use anyhow::Result; use middleware::AllBehaviours; use tokio::time::interval; @@ -121,20 +101,17 @@ enum KeyCommands { #[tokio::main] async fn main() -> Result<(), Box> { let opt = Opts::parse(); - match opt.cmd { - Some(Commands::Key(key_arg)) => { - match key_arg.cmd { - KeyCommands::Gen => { - let local_key = identity::generate_local_key(); - let base64_key = base64::engine::general_purpose::STANDARD - .encode(&local_key.to_protobuf_encoding()?); - tracing::info!("export KEY={}", base64_key); - tracing::info!("export PEER_ID={}", local_key.public().to_peer_id()); - } + if let Some(Commands::Key(key_arg)) = opt.cmd { + match key_arg.cmd { + KeyCommands::Gen => { + let local_key = identity::generate_local_key(); + let base64_key = base64::engine::general_purpose::STANDARD + .encode(&local_key.to_protobuf_encoding()?); + tracing::info!("export KEY={}", base64_key); + tracing::info!("export PEER_ID={}", local_key.public().to_peer_id()); } - return Ok(()); } - _ => {} + return Ok(()); } // load role let actor = @@ -166,7 +143,7 @@ async fn main() -> Result<(), Box> { .with_tokio() .with_tcp(tcp::Config::default(), noise::Config::new, yamux::Config::default)? .with_bandwidth_metrics(&mut metric_registry) - .with_behaviour(|key| AllBehaviours::new(key))? + .with_behaviour(AllBehaviours::new)? .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(u64::MAX))) .build(); @@ -247,7 +224,7 @@ async fn main() -> Result<(), Box> { if let Some(gossipsub_topic) = topics.get(commands[0]) { let message = serde_json::to_vec(&GOATMessage{ - actor: Actor::from_str(&commands[0]).unwrap(), + actor: Actor::from_str(commands[0]).unwrap(), content: commands[1].as_bytes().to_vec(), }).unwrap(); if let Err(e) = swarm @@ -322,7 +299,7 @@ async fn main() -> Result<(), Box> { SwarmEvent::NewExternalAddrOfPeer {peer_id, address} => { tracing::debug!("new external address of peer: {} {}", peer_id, address); } - SwarmEvent::ConnectionEstablished {peer_id, connection_id,endpoint, .. } => { + SwarmEvent::ConnectionEstablished {peer_id, connection_id, .. } => { tracing::debug!("connected to {peer_id}: {connection_id}"); } e => { diff --git a/node/src/metrics_service.rs b/node/src/metrics_service.rs index de778daf..6cf4837b 100644 --- a/node/src/metrics_service.rs +++ b/node/src/metrics_service.rs @@ -4,9 +4,9 @@ use std::{ }; use crate::rpc_service::AppState; -use axum::middleware::{FromFnLayer, Next}; +use axum::middleware::Next; use axum::{ - Router, extract::Request, extract::State, http::StatusCode, middleware, response::IntoResponse, + Router, extract::Request, extract::State, http::StatusCode, response::IntoResponse, routing::get, }; use http::HeaderMap; diff --git a/node/src/middleware/behaviour.rs b/node/src/middleware/behaviour.rs index bd24e72c..d7b545a3 100644 --- a/node/src/middleware/behaviour.rs +++ b/node/src/middleware/behaviour.rs @@ -1,20 +1,9 @@ #![feature(trivial_bounds)] use libp2p::identity::Keypair; -use libp2p::{ - gossipsub, kad, - kad::{Mode, store::MemoryStore}, - mdns, noise, - swarm::{StreamProtocol, SwarmEvent}, - tcp, yamux, -}; +use libp2p::{gossipsub, kad, kad::store::MemoryStore, mdns, swarm::StreamProtocol}; use libp2p_swarm_derive::NetworkBehaviour; -use std::error::Error; use std::time::Duration; -use tokio::{ - io::{self, AsyncBufReadExt}, - select, -}; -use tracing_subscriber::EnvFilter; +use tokio::io::{self}; // We create a custom network behaviour that combines Kademlia and mDNS. #[derive(NetworkBehaviour)] @@ -36,7 +25,7 @@ impl AllBehaviours { let gossipsub_config = gossipsub::ConfigBuilder::default() .max_transmit_size(262144) .build() - .map_err(|msg| io::Error::new(io::ErrorKind::Other, msg)) + .map_err(io::Error::other) .unwrap(); let gossipsub = gossipsub::Behaviour::new( gossipsub::MessageAuthenticity::Signed(key.clone()), diff --git a/node/src/middleware/mod.rs b/node/src/middleware/mod.rs index f0295b95..f5bada4d 100644 --- a/node/src/middleware/mod.rs +++ b/node/src/middleware/mod.rs @@ -1,8 +1,3 @@ -use std::error::Error; - -use futures::stream::StreamExt; -use tokio::io::AsyncBufReadExt; -use tracing_subscriber::EnvFilter; pub mod behaviour; pub use behaviour::AllBehaviours; diff --git a/node/src/rpc_service/handler/bitvm2_handler.rs b/node/src/rpc_service/handler/bitvm2_handler.rs index d21c70b6..4c12ce9d 100644 --- a/node/src/rpc_service/handler/bitvm2_handler.rs +++ b/node/src/rpc_service/handler/bitvm2_handler.rs @@ -6,17 +6,11 @@ use axum::extract::{Path, Query, State}; use bitcoin::Txid; use esplora_client::AsyncClient; use http::StatusCode; -use serde_json::json; use std::collections::HashMap; use std::default::Default; use std::str::FromStr; use std::sync::Arc; -use store::localdb::{ConnectionHolder, LocalDB, StorageProcessor}; -use store::{ - BridgeInStatus, BridgeOutStatus, BridgePath, Graph, GraphStatus, Instance, Message, - MessageState, -}; -use tokio::time::interval; +use store::{BridgeInStatus, BridgePath, Graph, GraphStatus, Instance, Message, MessageState}; use uuid::Uuid; #[axum::debug_handler] @@ -138,7 +132,7 @@ pub async fn graph_presign( instance.status = BridgeInStatus::Presigned.to_string(); let _ = tx.update_instance(instance.clone()).await?; let _ = tx.update_graph(graph.clone()).await?; - let _ = tx.commit().await?; + tx.commit().await?; Ok::>(resp_clone) }; match async_fn().await { diff --git a/node/src/rpc_service/handler/node_handler.rs b/node/src/rpc_service/handler/node_handler.rs index 0450696f..5d536b70 100644 --- a/node/src/rpc_service/handler/node_handler.rs +++ b/node/src/rpc_service/handler/node_handler.rs @@ -58,7 +58,7 @@ pub async fn get_nodes( ) .await?; - let mut node_desc_list: Vec = nodes + let node_desc_list: Vec = nodes .into_iter() .map(|v| { let status: String; diff --git a/node/src/rpc_service/mod.rs b/node/src/rpc_service/mod.rs index aea2005f..66056891 100644 --- a/node/src/rpc_service/mod.rs +++ b/node/src/rpc_service/mod.rs @@ -1,6 +1,5 @@ mod bitvm2; -pub use bitvm2::BridgeInTransactionPreparerRequest; use std::str::FromStr; mod handler; mod node; @@ -26,7 +25,6 @@ use http_body_util::BodyExt; use prometheus_client::registry::Registry; use std::sync::{Arc, Mutex}; use std::time::{Duration, UNIX_EPOCH}; -use store::localdb::LocalDB; use tokio::net::TcpListener; use tower_http::classify::ServerErrorsFailureClass; use tower_http::cors::{Any, CorsLayer}; @@ -48,7 +46,7 @@ pub struct AppState { impl AppState { pub async fn create_arc_app_state( - db_path: String, + db_path: &str, registry: Arc>, ) -> anyhow::Result> { let bitvm2_client = BitVM2Client::new( @@ -97,7 +95,7 @@ pub(crate) async fn serve( db_path: String, registry: Arc>, ) -> anyhow::Result<()> { - let app_state = AppState::create_arc_app_state(db_path, registry).await?; + let app_state = AppState::create_arc_app_state(&db_path, registry).await?; let add = app_state.clone(); let server = Router::new() .route("/", get(root)) @@ -203,29 +201,41 @@ mod tests { use prometheus_client::registry::Registry; use serde_json::json; use std::sync::{Arc, Mutex}; + use std::time::Duration; + use tokio::time::sleep; use tracing::info; use tracing_subscriber::EnvFilter; use uuid::Uuid; - const LISTEN_ADDRESS: &str = "127.0.0.1:8900"; - const TMEP_DB_PATH: &str = "/tmp/.bitvm2-node.db"; - fn init_tracing() { let _ = tracing_subscriber::fmt().with_env_filter(EnvFilter::from_default_env()).try_init(); } + + fn temp_file() -> String { + let tmp_db = tempfile::NamedTempFile::new().unwrap(); + tmp_db.path().as_os_str().to_str().unwrap().to_string() + } + + fn available_addr() -> String { + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.local_addr().unwrap().to_string() + } + #[tokio::test(flavor = "multi_thread")] async fn test_nodes_api() -> Result<(), Box> { init_tracing(); + let addr = available_addr(); tokio::spawn(rpc_service::serve( - LISTEN_ADDRESS.to_string(), - TMEP_DB_PATH.to_string(), + addr.clone(), + temp_file(), Arc::new(Mutex::new(Registry::default())), )); + sleep(Duration::from_secs(1)).await; let client = reqwest::Client::new(); let node_peer = "ddsdssccfsffsafafafa"; info!("=====>test api: create node"); let resp = client - .post(format!("http://{}/v1/nodes", LISTEN_ADDRESS)) + .post(format!("http://{}/v1/nodes", addr)) .json(&json!({ "peer_id": node_peer, "actor": "Challenger", @@ -240,8 +250,7 @@ mod tests { info!("Post Response: {}", res_body); info!("=====>test api: get node"); - let resp = - client.get(format!("http://{}/v1/nodes/{}", LISTEN_ADDRESS, node_peer)).send().await?; + let resp = client.get(format!("http://{}/v1/nodes/{}", addr, node_peer)).send().await?; info!("{:?}", resp); assert!(resp.status().is_success()); let res_body = resp.text().await?; @@ -251,7 +260,7 @@ mod tests { let resp = client .get(format!( "http://{}/v1/nodes?actor=Committee&status=Offline&offset=0&limit=5", - LISTEN_ADDRESS + addr )) .send() .await?; @@ -260,8 +269,7 @@ mod tests { info!("Post Response: {}", res_body); info!("=====>test api: get nodes overview"); - let resp = - client.get(format!("http://{}/v1/nodes/overview", LISTEN_ADDRESS)).send().await?; + let resp = client.get(format!("http://{}/v1/nodes/overview", addr)).send().await?; info!("{:?}", resp); assert!(resp.status().is_success()); let res_body = resp.text().await?; @@ -273,11 +281,13 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn test_bitvm2_api() -> Result<(), Box> { init_tracing(); + let addr = available_addr(); tokio::spawn(rpc_service::serve( - LISTEN_ADDRESS.to_string(), - TMEP_DB_PATH.to_string(), + addr.clone(), + temp_file(), Arc::new(Mutex::new(Registry::default())), )); + sleep(Duration::from_secs(1)).await; let instance_id = Uuid::new_v4().to_string(); let graph_id = Uuid::new_v4().to_string(); let from_addr = "tb1qsyngu9wf2x46tlexhpjl4nugv0zxmgezsx5erl"; @@ -285,8 +295,7 @@ mod tests { let client = reqwest::Client::new(); info!("=====>test api:/v1/instances/settings"); - let resp = - client.get(format!("http://{}/v1/instances/settings", LISTEN_ADDRESS)).send().await?; + let resp = client.get(format!("http://{}/v1/instances/settings", addr)).send().await?; info!("{:?}", resp); assert!(resp.status().is_success()); let res_body = resp.text().await?; @@ -294,7 +303,7 @@ mod tests { info!("=====>test api: test_bridge_in_tx_prepare"); let resp = client - .post(format!("http://{}/v1/instances/action/bridge_in_tx_prepare", LISTEN_ADDRESS)) + .post(format!("http://{}/v1/instances/action/bridge_in_tx_prepare", addr)) .json(&json!({ "instance_id": instance_id, "network": "testnet", @@ -324,7 +333,7 @@ mod tests { info!("=====>test api: get_instances"); let resp = client - .get(format!("http://{}/v1/instances/{}", LISTEN_ADDRESS, instance_id)) + .get(format!("http://{}/v1/instances/{}", addr, instance_id)) .send() .await .expect(""); @@ -334,10 +343,7 @@ mod tests { info!("=====>test api: get_instances_with_query_params"); let resp = client - .get(format!( - "http://{}/v1/instances?from_addr={}&offset=0&limit=5", - LISTEN_ADDRESS, from_addr - )) + .get(format!("http://{}/v1/instances?from_addr={}&offset=0&limit=5", addr, from_addr)) .send() .await?; assert!(resp.status().is_success()); @@ -345,15 +351,14 @@ mod tests { info!("Post Response: {}", res_body); info!("=====>test api: instance overview"); - let resp = - client.get(format!("http://{}/v1/instances/overview", LISTEN_ADDRESS,)).send().await?; + let resp = client.get(format!("http://{}/v1/instances/overview", addr)).send().await?; assert!(resp.status().is_success()); let res_body = resp.text().await?; info!("Post Response: {}", res_body); info!("=====>test api: create_graph"); let resp = client - .post(format!("http://{}/v1/graphs", LISTEN_ADDRESS)) + .post(format!("http://{}/v1/graphs", addr)) .json(&json!({ "instance_id": instance_id, "graph_id": graph_id, @@ -366,10 +371,7 @@ mod tests { info!("=====>test api: peg_btc_mint"); let resp = client - .post(format!( - "http://{}/v1/instances/{}/bridge_in/peg_gtc_mint", - LISTEN_ADDRESS, instance_id - )) + .post(format!("http://{}/v1/instances/{}/bridge_in/peg_gtc_mint", addr, instance_id)) .json(&json!({ "graph_ids":[ graph_id @@ -385,7 +387,7 @@ mod tests { let graph_state = "OperatorPresigned"; info!("=====>test api:update_graphs"); let resp = client - .put(format!("http://{}/v1/graphs/{}", LISTEN_ADDRESS, graph_id)) + .put(format!("http://{}/v1/graphs/{}", addr, graph_id)) .json(&json!({ "graph":{ "graph_id": graph_id, @@ -407,7 +409,7 @@ mod tests { // info!("=====>test api:get_graphs_list"); let resp = client - .get(format!("http://{}/v1/graphs?offset=0&limit=1", LISTEN_ADDRESS)) + .get(format!("http://{}/v1/graphs?offset=0&limit=1", addr)) .json(&json!({ "status": graph_state, "pegin_txid":pegin_tx @@ -419,15 +421,14 @@ mod tests { info!("Post Response: {}", res_body); info!("=====>test api:get_graph"); - let resp = - client.get(format!("http://{}/v1/graphs/{}", LISTEN_ADDRESS, graph_id)).send().await?; + let resp = client.get(format!("http://{}/v1/graphs/{}", addr, graph_id)).send().await?; assert!(resp.status().is_success()); let res_body = resp.text().await?; info!("Post Response: {}", res_body); info!("=====>test api:graph_presign"); let resp = client - .post(format!("http://{}/v1/graphs/{}/presign", LISTEN_ADDRESS, graph_id)) + .post(format!("http://{}/v1/graphs/{}/presign", addr, graph_id)) .json(&json!({ "instance_id": instance_id, "graph_ipfs_base_url":"https://ipfs.io/ipfs/QmXxwbk8eA2bmKBy7YEjm5w1zKiG7g6ebF1JYfqWvnLnhH" @@ -440,7 +441,7 @@ mod tests { info!("=====>test api:graph_presign_check"); let resp = client - .post(format!("http://{}/v1/graphs/presign_check", LISTEN_ADDRESS)) + .post(format!("http://{}/v1/graphs/presign_check", addr)) .json(&json!( { "instance_id": instance_id, diff --git a/node/src/rpc_service/node.rs b/node/src/rpc_service/node.rs index ce96c149..ad63eee2 100644 --- a/node/src/rpc_service/node.rs +++ b/node/src/rpc_service/node.rs @@ -1,7 +1,6 @@ -use crate::rpc_service::current_time_secs; use bitvm2_lib::actors::Actor; use serde::{Deserialize, Serialize}; -use store::{Node, NodesOverview}; +use store::NodesOverview; pub const ALIVE_TIME_JUDGE_THRESHOLD: i64 = 4 * 3600; // the input to our `create_user` handler diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..5d56faf9 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly"