diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 22eb542971..4ce9a3af19 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -112,13 +112,13 @@ fn get_igor_genesis_block_raw() -> Block { // Note: Use print_new_genesis_block_igor in core/tests/helpers/block_builders.rs to generate the required fields // below let sig = Signature::new( - PublicKey::from_hex("e22ad0f02bfc08e3b04c667cca050072e091a477c3a4d10345c4114ed4266818").unwrap(), - PrivateKey::from_hex("2685f18306717ed7ccfad9f96185e5cbca52b3fe109673b1075d130fad54f60e").unwrap(), + PublicKey::from_hex("00f3a682fd38a79da6666301a727953ab55b880cd49b3c1bb24b2671756bce6a").unwrap(), + PrivateKey::from_hex("7dbba37445fadf0fa0a64fc0b52afa652fb487b92429634298d83d794b38d905").unwrap(), ); let coinbase_meta_sig = CommitmentSignature::new( - Commitment::from_hex("ecab12e0bab23ab32a0014b592fcdb4d22be7e02cb5031632ad9c3c9b2560229").unwrap(), - PrivateKey::from_hex("8a87214524cb2025a3dbaaf7cb5a6287c4d37f7521e667cdc253909adb48c70e").unwrap(), - PrivateKey::from_hex("6b5f940eaba65b6a46edc112ab9186be9310aeb086cf0878a68bccf73f712600").unwrap(), + Commitment::from_hex("ac07390c975c96d3ebe6bc591571f31edd5426f89e0c5b8a8552d2bcdc335b43").unwrap(), + PrivateKey::from_hex("1a5c8bf91d85ac3a9bb616caae072f95f1a8629cbfec712a5f3cdb94981da502").unwrap(), + PrivateKey::from_hex("40976c932da8f0ee0adce6861fb3860639af6e38e280be0108bd80127ff78607").unwrap(), ); let mut body = AggregateBody::new( vec![], @@ -129,14 +129,14 @@ fn get_igor_genesis_block_raw() -> Block { .. Default::default() }, Commitment::from_hex( - "dc07cc8ad8106d33d38239f63bc308959f48d47c8dbe2a65e32662b93262ba09", + "acab973deac0b901fc966934f33e53e84be0902b863d6b31c07aee1077bb6d74", ) .unwrap(), - BulletRangeProof::from_hex("01002c676a37bd85610b752598fdc493b0d0023b752b5c620e052731ae1278721dcc1ac376f04e6196083a830115a07452a79c82334b2130bec19784dc60d7dd4418f1fafe27b7519ba72c12dad7e8aa98ca52b5db9e051dc8d58a39f47157d72496c13c839f89fa58fa0c9303d2bf2d51bd8fbe00105602c69a75b9d1f9673f75a6abc51ab102e2ffafe96c5b13d49e2eae5a506d768dd4647aee98fa75b9a364cc3c29b0c01ca7fcc6fbf212e592f68bf104ef2c1cc5202ec500e5b37949e95062090b3d947427a7459b128215dbe75629656651362298691a8ef895d7b0bb3090b15b807a38eba20da1349dbc9bd6bb221fee6a79183433ddac29ef2027877a0230eda904e275ab6c9d87d9d2ea0fca13c92cb678edf5782eea1bdcec0d200c944a9e8c0a20ddcbc9e107ec7a84e7a6a498ba059f9bd9aded2c427a8c021e1c28e961c2f6cc4f490fda74407d99ac3cd54737050e68d7208eea5a7cfa85000fded0cfc6422a66da834bdcb14402bf1857467619143ded6de7a454b778dc1015f848bd278fe2d415334bc29b1113a76bcac126d00a9803ed931ec56fa9f085428ac9197191295e05bbae762092f0918d489a4e39e7220d91f2fc0a7de9b45676eee23c36d05967dd00073e436992456adf5974c3acc618fc11b6a216d8647a6fbaf033cd25898ee229002fec218f531a8de40d0dc4a352296bb92ececc5f4f0e46c1f81ba195fa8a667258bcabe027a44ccee5154fa2821b90ce2694c90883028db0ccd61c59fc8123b9d60bc3a4ed6024addee150c04f0cf410701a865fae07").unwrap(), + BulletRangeProof::from_hex("015af6dfef9563da065ac5d55eee0acda4a321222c75ef5c4415b0968c4f923d4f62cef4b10f247b4ccfcde7c83dff19605301af7c79a08d9bdd78d6911b3c2d017e124a1787a7f2bc7fe0f4785d11ce979c7d22774f9c45c063767144cc94c53d64936606452e2fb278094fb91ff3fc4eda9791e8f27f124bca489c3f7c979e04a2a42074c4aa23551a1cb1b132c2af01b9b3541632aaeaef0b2be48f7e61465d2829f7719eaff4127f5d19217ff6a36a19ea8bfb22aa0a453882528a6488be3d4652f275dc82f675eedebe6c32a691e80da39a48a833d26e07b733a253c804382286a3d6d9563d1c42fd4894694c70f07dcbaa21d014dbf900d2a176ce147326dc73e344cbdbc7866034693680bc7b4396bb1b1e1e6995d3564ae7c3884447561019ecbd60b45804aae214115320e2768565e1a145504e9dc95aed921824cd0c6083fefe5a328f17759f47e9288e57dad841e56b1a2a34b2d1416b4c7758e425c2b5925e957a3b78bec21f05c6bd7e0b4c259bc500247f4b0068134a343a90659a48e2ac11f2b1f890352c3b260fa78cb16d0a1d5459c6411ba34993bac7da6c1a662787ee15146a3c8623dff7fb7fa4143caeb431f53c6be02ef260d36eeb209273ff1c5a50413f61d8046ae6bac9e17c198503d602c10165d17522519aa7306b39661e3200a65fe234f67e125e80bdf46019f422325af7743d3ef873bb3e0ba2b2ca472170bd25168ad83870af30245ec5e7f464d2119054f76be999f90d07510193e01135ce0f16026b00128913fae48f2f8612a1fd5f7e4e40cb33c36c09").unwrap(), // For genesis block: A default script can never be spent, intentionally script!(Nop), // Script offset never checked for coinbase, thus can use default - PublicKey::from_hex("9234814d039bf3ac6545ed40a63570a2720b9376dcbde0bc1a75d081eec50446").unwrap(), + PublicKey::from_hex("7048544e58d20ae730105da01a0bdb2cd3b968c15a030a7d280ac69d7a7a1f30").unwrap(), // For genesis block: Metadata signature will never be checked coinbase_meta_sig, Covenant::default(), @@ -149,7 +149,7 @@ fn get_igor_genesis_block_raw() -> Block { MicroTari(0), 0, Commitment::from_hex( - "18d80887a36fae6c2cbef5941d5eedd927aeae1003798bb63c3f292cb68cbe00", + "8ecaca61f68daea32874526b81aa909dd6b36e807b7825ad3d2943070bb30f1e", ) .unwrap(), sig,None @@ -158,7 +158,7 @@ fn get_igor_genesis_block_raw() -> Block { ); body.sort(); // set genesis timestamp - let genesis = DateTime::parse_from_rfc2822("08 Aug 2022 10:00:00 +0200").unwrap(); + let genesis = DateTime::parse_from_rfc2822("30 Aug 2022 11:48:00 +0100").unwrap(); #[allow(clippy::cast_sign_loss)] let timestamp = genesis.timestamp() as u64; Block { @@ -167,11 +167,11 @@ fn get_igor_genesis_block_raw() -> Block { height: 0, prev_hash: FixedHash::zero(), timestamp: timestamp.into(), - output_mr: FixedHash::from_hex("55cd15eb1966b15e3dc8f8066371702a86b573915cd409cf8c20c7529a73c027").unwrap(), - witness_mr: FixedHash::from_hex("188b79e4cd780914fc0dfe7d57b9f32bfae04293052b867fce25c4af8b5191dc") + output_mr: FixedHash::from_hex("30e3813df61c3fb129c92f78e32422b362a12f6610e13adc6c8d7f6b952443e5").unwrap(), + witness_mr: FixedHash::from_hex("6adf5e059d7fc60e1c5a0954556adf8246d5c60554fce7d2fddcb338a870acd8") .unwrap(), output_mmr_size: 1, - kernel_mr: FixedHash::from_hex("2e3fde9cd20b48f699523d1b107b4742c6aa03ed1cb210f580d0c7426463b966").unwrap(), + kernel_mr: FixedHash::from_hex("22e57d85985535c197554232f9d223dc3575d57378ef7a4198905ebb515daf71").unwrap(), kernel_mmr_size: 1, input_mr: FixedHash::zero(), total_kernel_offset: PrivateKey::from_hex( @@ -214,26 +214,26 @@ pub fn get_esmeralda_genesis_block() -> ChainBlock { block.body.sort(); // Use this code if you need to generate new Merkle roots - // NB: `esmerlada_genesis_sanity_check` must pass + // NB: `esmeralda_genesis_sanity_check` must pass // // use croaring::Bitmap; // use std::convert::TryFrom; // use crate::{KernelMmr, MutableOutputMmr, WitnessMmr}; - // + // let mut kernel_mmr = KernelMmr::new(Vec::new()); // for k in block.body.kernels() { // println!("k: {}", k); // kernel_mmr.push(k.hash().to_vec()).unwrap(); // } - // + // let mut witness_mmr = WitnessMmr::new(Vec::new()); // let mut output_mmr = MutableOutputMmr::new(Vec::new(), Bitmap::create()).unwrap(); - // + // for o in block.body.outputs() { // witness_mmr.push(o.witness_hash().to_vec()).unwrap(); // output_mmr.push(o.hash().to_vec()).unwrap(); // } - // + // block.header.kernel_mr = FixedHash::try_from(kernel_mmr.get_merkle_root().unwrap()).unwrap(); // block.header.witness_mr = FixedHash::try_from(witness_mmr.get_merkle_root().unwrap()).unwrap(); // block.header.output_mr = FixedHash::try_from(output_mmr.get_merkle_root().unwrap()).unwrap(); @@ -243,11 +243,11 @@ pub fn get_esmeralda_genesis_block() -> ChainBlock { // Hardcode the Merkle roots once they've been computed above block.header.kernel_mr = - FixedHash::from_hex("1bfbc0e257b4876a88025bc07d5a9bc09dde36441fcb597dcee326ab76b90eed").unwrap(); + FixedHash::from_hex("49bec44ce879f529523c593d2f533fffdc2823512d673e78e1bb6b2c28d9fcf5").unwrap(); block.header.witness_mr = - FixedHash::from_hex("0abe819c208dc98149699dd009715b8e302c666b3322a67d31f1d74a0593999f").unwrap(); + FixedHash::from_hex("8e6bb075239bf307e311f497d35c12c77c4563f218c156895e6630a7d9633de3").unwrap(); block.header.output_mr = - FixedHash::from_hex("69b9646e0e57a64a4ab44d05e6c45146bfc02c7449cf5cc6e404190064ee4309").unwrap(); + FixedHash::from_hex("163304b3fe0f9072170db341945854bf88c8e23e23ecaac3ed86b9231b20e16f").unwrap(); let accumulated_data = BlockHeaderAccumulatedData { hash: block.hash(), @@ -265,13 +265,13 @@ fn get_esmeralda_genesis_block_raw() -> Block { // Note: Use print_new_genesis_block_esmeralda in core/tests/helpers/block_builders.rs to generate the required // fields below let excess_sig = Signature::new( - PublicKey::from_hex("9e6be7c87533b2e01763de34c309b1c283e5e5e91500a43856a78dcb26b4233f").unwrap(), - PrivateKey::from_hex("6dc0083f9f4b0deb85b34e6d32598e77a729d6f695568322f461d006929dbb04").unwrap(), + PublicKey::from_hex("70e343b603ec1e0422b02e68d1051675e48b1d7aa26a46d79c0fa104762e1161").unwrap(), + PrivateKey::from_hex("8d9ea6626b108ff5479c6378f605a9ffa9e3908ca2e374797d45957a26e9810b").unwrap(), ); let coinbase_meta_sig = CommitmentSignature::new( - Commitment::from_hex("841ae8f109a4fcefb2522de04ebff133288156f9ebd3380c42727b41df9e3b15").unwrap(), - PrivateKey::from_hex("7270bc342a378be7b16aa5ff6d5e231fd0acfa4cd46f64a4872e42465f2a7b0c").unwrap(), - PrivateKey::from_hex("51a18d5eb531cee771765a8b4ae5444e17c508549cdba62d942d172a247b0709").unwrap(), + Commitment::from_hex("2432288b75a39e102de18a4556533bd340e0e6fd682d7d405fd5c9d834eb0f65").unwrap(), + PrivateKey::from_hex("3dbc5debc8cd2d983bc09322488bc0cd60531e198f2925b2d0175ff0ef0efa0f").unwrap(), + PrivateKey::from_hex("12cb8b669a8d16d78f2760529b651adc8213c41364c861cc0a2e218a0ce3db0a").unwrap(), ); let coinbase = TransactionOutput::new( TransactionOutputVersion::get_current_version(), @@ -282,12 +282,12 @@ fn get_esmeralda_genesis_block_raw() -> Block { metadata: Vec::new(), sidechain_features: None, }, - Commitment::from_hex("2afed894ae877b5e9c7450cc0e29de46aeb6b118cd3d6b0a77da8c8156a1e234").unwrap(), - BulletRangeProof::from_hex("0136b44930772f85b17139dd8e83789f84ccc2134cf6b2416d908fb8403efa4d3bc0247ec4afbbb1f7f7498d129226f26199eec988bd3e5ccce2572fd7aee16f2c4a2d710fac0e3bc1d612d700af2265e230ae1c45e3b0e4d3aab43cb87534217b56dcdb6598ed859d0cd6d70fae5acaaa38db5bbae6df8339e5e3dd594388bd53cef6f2acda4ac002d8ac6e01d430bdcf8565b8b8823ff3fb7dc8b359e687dd6feab0edf86c7444c713f34d2513145049b9664aae2e3dbc8a3365baae9d26842852ec9f401112a9742560ec220e61b05f65448d75b714839a6bafc723e9a04f25c69c036775fc55b7ec2bb28ef1de25a32cac51c288ed6d43f3819b1c3356d7699ea5f10217d553e90e6c93641649bd289dedb9e5725579539df07301f15093496c8fca3ec66a43332d1be3a3f94b530e1b8ca7feaa24c4ca73e60397a786ab742ac8933ba6bd504ef3c1a53fa1ff4397aba7c42a526507f930fdf9ff00a2a07b521841574d4e2b5beece946a15fa2545c8e556e704eed0ed10c0e3cbb9f5d6147e6e2d260666c79fa04d89c8901eeb3d3793239a68218a2c105f1bcb4211631eea037102bd5c840de751d84f473bb5cf6c41b3b97ec1c978700ec3c132e09a28d0a92c7e141e9968d0d2852c339a85c052356049f6752cb57c3d2b8c03db24525aa1f7db4a4f4d7d48639e27faa8c8bc695ad6c4f7688d43feedabef4d05c20b349ebc1697b3b899038b22fa308546efff290902cdacbe9992450cc31b61fc00652cffe4335c080d8398b061add986626068e17d5982ee9f6f28b4f4579d0406").unwrap(), + Commitment::from_hex("46eec110cf173557e149d453734f6707fea9ed27c9a0dd0276bb43eb1f6e3322").unwrap(), + BulletRangeProof::from_hex("01b05c72ea976764b8f9a56bb302990829dacae5f9b2d26e028e97c66a7ac3a14c7809ea5da55fb1e88a16195619d67381f28181b1ad7e0c9661c726e1c56ad7770eb75e314b51a89d716a2dd7737b26a40d8e956911ff45d4c47a1164edae5505aaca58ec6f95762daaa02545dc2ce502e9892d98422849352b6dbcc3322b6b1adae4d33461dd8b5b75b4a9bf52b3e3b00ef7579b16e59f17f43c45ea5e82db063c23ce2d214f93a211cd8f7a3cb220071c68ba3a348b082c3eebb8b6d6339d18decd0372b82e762a9f16e5e7ed23b21c1025ba093b676c55cfa603d888bcc315bc95e8e4bebad9ec51124aab0fe4a8abfc9053db1fb1560c5214b9485826e0127448a2aa84c25f17c5833b15bf434903db7a676bfb11ace2ece255b018428457122da112d481c8a742f916cca069b874e6762248fbb00fa6895f7d4b8a9a8829164baf6ad1d3ad5775c679766ead9da782977fdeb5af7e4b2eb6828e87551179f888ed1c598dd1b81c46b335fb4a827fadf7669e007ff4ed6f260d0bde3eb42282983f58bb0f11a44e064a80503154f4cdb76537192411b2755c2b453b90b3754e9253e64837f15c933b7a479fbb9b1ea8d45364fff67b4aa71ecf67f16c497b5846ff50aaae882e71ac5e6f3ba29189d03da3ed91511074747db413a3e8f90fd9b8fa0751e8ecde29324f4fe8d9023405e33e0d07741056941f9593e8931d0c22553af6447d5c38c762e45afaa89cc11c6843e77430cea44b41fcef0ad11d08d3be1f279ee791fd3b4a8b39d2889a51a4cb2a81885ef6cab119e8de29908a0e").unwrap(), // A default script can never be spent, intentionally script!(Nop), // The Sender offset public key is not checked for coinbase outputs - PublicKey::from_hex("1e036eb452b9098b48edeaa3b91716502fc4786e1ac4363046546f28d26bb337").unwrap(), + PublicKey::from_hex("f649c442e31f6633099549d08870f6c16e1265af797c941ab93a264aba53ff69").unwrap(), // For genesis block: Metadata signature will never be checked coinbase_meta_sig, // Covenant @@ -301,14 +301,14 @@ fn get_esmeralda_genesis_block_raw() -> Block { KernelFeatures::COINBASE_KERNEL, MicroTari(0), 0, - Commitment::from_hex("2480268904dbe6cb4b4af290fd51b43383588a575c926af674311691e5a6cc59").unwrap(), + Commitment::from_hex("c88376c6b1cd801821e18f199012f07eae50078177c0406fee3bff7f851e5e66").unwrap(), excess_sig, None, ); let mut body = AggregateBody::new(vec![], vec![coinbase], vec![kernel]); body.sort(); // set genesis timestamp - let genesis = DateTime::parse_from_rfc2822("24 Aug 2022 22:00:00 +0200").unwrap(); + let genesis = DateTime::parse_from_rfc2822("30 Aug 2022 11:45:00 +0100").unwrap(); #[allow(clippy::cast_sign_loss)] let timestamp = genesis.timestamp() as u64; Block { @@ -317,11 +317,11 @@ fn get_esmeralda_genesis_block_raw() -> Block { height: 0, prev_hash: FixedHash::zero(), timestamp: timestamp.into(), - output_mr: FixedHash::from_hex("49a0bfcf8dd896d59ab2eb1c5a8c96b49cce5ef9c4bed1a172cc2cd713b2a04d").unwrap(), - witness_mr: FixedHash::from_hex("bd043cfe6304c0cb2b6cdbc6ad52c03ff893f3b53631be41846fbac75c422c7e") + output_mr: FixedHash::from_hex("e6fbb394caca64f9fd2e68cbd0406a279c7c7d0e942281934530711e3030f4e8").unwrap(), + witness_mr: FixedHash::from_hex("68c0fa430ec073acea47116ebd23ba896df86217dd016f3a131d455cadc3c246") .unwrap(), output_mmr_size: 1, - kernel_mr: FixedHash::from_hex("df4d2a7d15da3485b8fcaf0524f1ee5d409883bbe8901c4df69543b056763d42").unwrap(), + kernel_mr: FixedHash::from_hex("157ab76af27428ff7bca4d910908bae698df34a6dcaf43a1d11a97fa3e67539a").unwrap(), kernel_mmr_size: 1, input_mr: FixedHash::zero(), total_kernel_offset: PrivateKey::from_hex( diff --git a/base_layer/core/src/transactions/transaction_components/mod.rs b/base_layer/core/src/transactions/transaction_components/mod.rs index 6261eea1bf..23efa56f09 100644 --- a/base_layer/core/src/transactions/transaction_components/mod.rs +++ b/base_layer/core/src/transactions/transaction_components/mod.rs @@ -32,7 +32,7 @@ pub use output_features::OutputFeatures; pub use output_features_version::OutputFeaturesVersion; pub use output_type::OutputType; pub use side_chain::*; -use tari_common_types::types::{Commitment, FixedHash}; +use tari_common_types::types::{Commitment, FixedHash, PublicKey}; use tari_script::TariScript; pub use transaction::Transaction; pub use transaction_builder::TransactionBuilder; @@ -92,6 +92,7 @@ pub(super) fn hash_output( script: &TariScript, covenant: &Covenant, encrypted_value: &EncryptedValue, + sender_offset_public_key: &PublicKey, minimum_value_promise: MicroTari, ) -> FixedHash { let common_hash = DomainSeparatedConsensusHasher::::new("transaction_output") @@ -101,6 +102,7 @@ pub(super) fn hash_output( .chain(script) .chain(covenant) .chain(encrypted_value) + .chain(sender_offset_public_key) .chain(&minimum_value_promise); match version { diff --git a/base_layer/core/src/transactions/transaction_components/transaction_input.rs b/base_layer/core/src/transactions/transaction_components/transaction_input.rs index ccbf137ae0..a83950b922 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_input.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_input.rs @@ -344,6 +344,7 @@ impl TransactionInput { features, covenant, encrypted_value, + sender_offset_public_key, minimum_value_promise, .. } => transaction_components::hash_output( @@ -353,6 +354,7 @@ impl TransactionInput { script, covenant, encrypted_value, + sender_offset_public_key, *minimum_value_promise, ), } @@ -364,34 +366,13 @@ impl TransactionInput { /// Implement the canonical hashing function for TransactionInput for use in ordering pub fn canonical_hash(&self) -> Result { - match self.spent_output { - SpentOutput::OutputHash(_) => Err(TransactionError::MissingTransactionInputData), - SpentOutput::OutputData { - ref version, - ref features, - ref commitment, - ref script, - ref sender_offset_public_key, - ref covenant, - ref encrypted_value, - ref minimum_value_promise, - } => { - // TODO: Change this hash to what is in RFC-0121/Consensus Encoding #testnet-reset - let writer = DomainSeparatedConsensusHasher::::new("transaction_input") - .chain(version) - .chain(features) - .chain(commitment) - .chain(script) - .chain(sender_offset_public_key) - .chain(&self.script_signature) - .chain(&self.input_data) - .chain(covenant) - .chain(encrypted_value) - .chain(minimum_value_promise); - - Ok(writer.finalize().into()) - }, - } + let writer = DomainSeparatedConsensusHasher::::new("transaction_input") + .chain(&self.version) + .chain(&self.script_signature) + .chain(&self.input_data) + .chain(&self.output_hash()); + + Ok(writer.finalize().into()) } pub fn set_maturity(&mut self, maturity: u64) -> Result<(), TransactionError> { diff --git a/base_layer/core/src/transactions/transaction_components/transaction_output.rs b/base_layer/core/src/transactions/transaction_components/transaction_output.rs index d1f0004f63..ca75c3ba42 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_output.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_output.rs @@ -169,6 +169,7 @@ impl TransactionOutput { &self.script, &self.covenant, &self.encrypted_value, + &self.sender_offset_public_key, self.minimum_value_promise, ) } diff --git a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs index ccbfa52f5c..132d143cb2 100644 --- a/base_layer/core/src/transactions/transaction_components/unblinded_output.rs +++ b/base_layer/core/src/transactions/transaction_components/unblinded_output.rs @@ -346,6 +346,7 @@ impl UnblindedOutput { &self.script, &self.covenant, &self.encrypted_value, + &self.sender_offset_public_key, self.minimum_value_promise, ) } diff --git a/base_layer/core/src/validation/helpers.rs b/base_layer/core/src/validation/helpers.rs index c79f47978f..f771647284 100644 --- a/base_layer/core/src/validation/helpers.rs +++ b/base_layer/core/src/validation/helpers.rs @@ -380,46 +380,8 @@ pub fn check_input_is_utxo(db: &B, input: &TransactionInpu // We know that the commitment exists in the UTXO set. Check that the output hash matches (i.e. all fields // like output features match) if utxo_hash == output_hash { - // Check that the input found by commitment, matches the input given here - match db - .fetch_output(&utxo_hash)? - .and_then(|output| output.output.into_unpruned_output()) - { - Some(output) => { - let mut compact = input.to_compact(); - compact.add_output_data( - output.version, - output.features, - output.commitment, - output.script, - output.sender_offset_public_key, - output.covenant, - output.encrypted_value, - output.minimum_value_promise, - ); - let input_hash = input.canonical_hash()?; - if compact.canonical_hash()? != input_hash { - warn!( - target: LOG_TARGET, - "Input '{}' spends commitment '{}' found in the UTXO set but does not contain the \ - matching metadata fields.", - input_hash.to_hex(), - input.commitment()?.to_hex(), - ); - return Err(ValidationError::UnknownInput); - } - }, - None => { - error!( - target: LOG_TARGET, - "🚨 Output '{}' was in unspent but was pruned - this indicates a blockchain database \ - inconsistency!", - output_hash.to_hex() - ); - return Err(ValidationError::UnknownInput); - }, - } - + // Because the retrieved hash matches the new input.output_hash() we know all the fields match and are all + // still the same return Ok(()); } @@ -434,7 +396,8 @@ pub fn check_input_is_utxo(db: &B, input: &TransactionInpu input, output ); - return Err(ValidationError::BlockError(BlockValidationError::InvalidInput)); + + return Err(ValidationError::UnknownInput); } // Wallet needs to know if a transaction has already been mined and uses this error variant to do so. diff --git a/base_layer/tari_mining_helper_ffi/src/lib.rs b/base_layer/tari_mining_helper_ffi/src/lib.rs index 3375012bff..09a8948cae 100644 --- a/base_layer/tari_mining_helper_ffi/src/lib.rs +++ b/base_layer/tari_mining_helper_ffi/src/lib.rs @@ -370,8 +370,8 @@ mod tests { #[test] fn detect_change_in_consensus_encoding() { - const NONCE: u64 = 11718790012985321443; - const DIFFICULTY: Difficulty = Difficulty::from_u64(3755); + const NONCE: u64 = 15151693527177504675; + const DIFFICULTY: Difficulty = Difficulty::from_u64(8707); unsafe { let mut error = -1; let error_ptr = &mut error as *mut c_int; diff --git a/base_layer/wallet/src/transaction_service/protocols/transaction_validation_protocol.rs b/base_layer/wallet/src/transaction_service/protocols/transaction_validation_protocol.rs index e6f4f50265..28882f9752 100644 --- a/base_layer/wallet/src/transaction_service/protocols/transaction_validation_protocol.rs +++ b/base_layer/wallet/src/transaction_service/protocols/transaction_validation_protocol.rs @@ -461,6 +461,23 @@ where mined_timestamp: u64, num_confirmations: u64, ) -> Result<(), TransactionServiceProtocolError> { + // This updates the OMS first before we update the TMS. If we update the TMS first and operation fail inside of + // the OMS, we have two databases that are out of sync, as the TMS would have been updated and OMS will be stuck + // forever as pending_incoming. + self.output_manager_handle + .set_coinbase_abandoned(tx_id, true) + .await + .map_err(|e| { + warn!( + target: LOG_TARGET, + "Could not mark coinbase output for TxId: {} as abandoned: {} (Operation ID: {})", + tx_id, + e, + self.operation_id + ); + e + }) + .for_protocol(self.operation_id)?; self.db .set_transaction_mined_height( tx_id, @@ -479,15 +496,6 @@ where .await .for_protocol(self.operation_id)?; - if let Err(e) = self.output_manager_handle.set_coinbase_abandoned(tx_id, true).await { - warn!( - target: LOG_TARGET, - "Could not mark coinbase output for TxId: {} as abandoned: {} (Operation ID: {})", - tx_id, - e, - self.operation_id - ); - }; self.publish_event(TransactionEvent::TransactionCancelled( tx_id, TxCancellationReason::AbandonedCoinbase, diff --git a/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs b/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs index 753fd3cf14..9e1db00891 100644 --- a/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs +++ b/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs @@ -210,6 +210,7 @@ pub async fn oms_reply_channel_task( let (request, reply_tx) = request_context.split(); let response = match request { OutputManagerRequest::CancelTransaction(_) => Ok(OutputManagerResponse::TransactionCancelled), + OutputManagerRequest::SetCoinbaseAbandoned(_, _) => Ok(OutputManagerResponse::CoinbaseAbandonedSet), _ => Err(OutputManagerError::InvalidResponseError( "Unhandled request type".to_string(), )), diff --git a/common/config/presets/b_peer_seeds.toml b/common/config/presets/b_peer_seeds.toml index 7b07a2545c..82a85ea891 100644 --- a/common/config/presets/b_peer_seeds.toml +++ b/common/config/presets/b_peer_seeds.toml @@ -20,24 +20,18 @@ dns_seeds = ["seeds.esmeralda.tari.com"] # Custom specified peer seed nodes peer_seeds = [ - # 333388d1cbe3e2bd17453d052f - "c2eca9cf32261a1343e21ed718e79f25bfc74386e9305350b06f62047f519347::/onion3/6yxqk2ybo43u73ukfhyc42qn25echn4zegjpod2ccxzr2jd5atipwzqd:18141", - # 555575715a49fc242d756e52ca - "42fcde82b44af1de95a505d858cb31a422c56c4ac4747fbf3da47d648d4fc346::/onion3/2l3e7ysmihc23zybapdrsbcfg6omtjtfkvwj65dstnfxkwtai2fawtyd:18141", - # 77771f53be07fab4be5f1e1ff7 - "50e6aa8f6c50f1b9d9b3d438dfd2a29cfe1f3e3a650bd9e6b1e10f96b6c38f4d::/onion3/7s6y3cz5bnewlj5ypm7sekhgvqjyrq4bpaj5dyvvo7vxydj7hsmyf5ad:18141", - # 9999016f1f3a6162dddf5a45aa - "36a9df45e1423b5315ffa7a91521924210c8e1d1537ad0968450f20f21e5200d::/onion3/v24qfheti2rztlwzgk6v4kdbes3ra7mo3i2fobacqkbfrk656e3uvnid:18141", - # bbbb8358387d81c388fadb4649 - "be128d570e8ec7b15c101ee1a56d6c56dd7d109199f0bd02f182b71142b8675f::/onion3/ha422qsy743ayblgolui5pg226u42wfcklhc5p7nbhiytlsp4ir2syqd:18141", - # eeeeb0a943ed143e613a135392 - "3e0321c0928ca559ab3c0a396272dfaea705efce88440611a38ff3898b097217::/onion3/sl5ledjoaisst6d4fh7kde746dwweuge4m4mf5nkzdhmy57uwgtb7qqd:18141", - # 66664a0f95ce468941bb9de228 - "b0f797e7413b39b6646fa370e8394d3993ead124b8ba24325c3c07a05e980e7e::/ip4/35.177.93.69/tcp/18189", - # 22221bf814d5e524fce9ba5787 - "0eefb45a4de9484eca74846a4f47d2c8d38e76be1fec63b0112bd00d297c0928::/ip4/13.40.98.39/tcp/18189", - # 4444a0efd8388739d563bdd979 - "544ed2baed414307e119d12894e27f9ddbdfa2fd5b6528dc843f27903e951c30::/ip4/13.40.189.176/tcp/18189" + # 00000df938d2615412b1e9fe9b + "68667362ceadf4543f4bac3a47e8bd1b6c5cbdab90fa781392e419b8ee03a153::/onion3/lf2p2zwuinjkk4bzzwddbol64x5ycofanja25zu2oxmrofa3nk43ypyd:18141", + # 33333faa19573c7d4c35d54c68 + "a482e5541dfc76b53bddda5ad68a8bdec290c862e6e5c716e6014acd65347411::/onion3/3mpymjycel3ufraw55cnl5tvednrnzmqvq56vaydswnboibkja2d4tid:18141", + # 55555c74402e51a342a92afaea + "fe67c469fe61f31765f43ec781dcdde78092204d36bbdc544cb09ca41d495e06::/onion3/tbmffvb67hf2ujfh5md6n2hhgi5guao2ahmv54bh3vr5x3wjor2u5cid:18141", + # 88888dfde986ebd7a40966169e + "3cf5da9cecaf347b6fcfee9c8751be9fad529878572b19da3bd24c9704ab2426::/onion3/jxh2bl4zunbrd3y7pgayvcj3l4iczcne2s5h47lclv6e3kjzxbaplgqd:18141", + # 222223a86f76f1d09c05ef96cd + "18df727907476f455809d3794cfec1d489b6bf305d06467e8cf5cb102402530b::/onion3/vv26lxr727pvvxbmgf3sdbobqsqqfrtasfkavs4js5vlq3lk34a54hid:18141", + # 444447b8fdcfc7458f727ef9a2 + "72468fae60e65218276793eabb764ed7280049bb74560ca18710755234bcce49::/onion3/oqpd4wgd7tzagvvgkfwrdu6ssvoqaw4zdoqhvutof2flgkgj6gwrpfqd:18141", ] [igor.p2p.seeds] diff --git a/comms/core/src/test_utils/mocks/connectivity_manager.rs b/comms/core/src/test_utils/mocks/connectivity_manager.rs index 6dda3f9f0e..ae29b9211c 100644 --- a/comms/core/src/test_utils/mocks/connectivity_manager.rs +++ b/comms/core/src/test_utils/mocks/connectivity_manager.rs @@ -63,6 +63,7 @@ struct State { active_conns: HashMap, pending_conns: HashMap>>>, selected_connections: Vec, + banned_peers: Vec<(NodeId, Duration, String)>, connectivity_status: ConnectivityStatus, } @@ -175,6 +176,10 @@ impl ConnectivityManagerMockState { self.event_tx.send(event).unwrap(); } + pub async fn take_banned_peers(&self) -> Vec<(NodeId, Duration, String)> { + self.with_state(|state| state.banned_peers.drain(..).collect()).await + } + pub(self) async fn with_state(&self, f: F) -> R where F: FnOnce(&mut State) -> R { let mut lock = self.inner.lock().await; @@ -263,7 +268,13 @@ impl ConnectivityManagerMock { unimplemented!() }, GetAllConnectionStates(_) => unimplemented!(), - BanPeer(_, _, _) => {}, + BanPeer(node_id, duration, reason) => { + self.state + .with_state(|state| { + state.banned_peers.push((node_id, duration, reason)); + }) + .await + }, AddPeerToAllowList(_) => {}, RemovePeerFromAllowList(_) => {}, GetActiveConnections(reply) => { diff --git a/comms/dht/src/network_discovery/discovering.rs b/comms/dht/src/network_discovery/discovering.rs index 43a7ff2ee6..a5ae679a37 100644 --- a/comms/dht/src/network_discovery/discovering.rs +++ b/comms/dht/src/network_discovery/discovering.rs @@ -35,7 +35,12 @@ use super::{ state_machine::{DhtNetworkDiscoveryRoundInfo, DiscoveryParams, NetworkDiscoveryContext, StateEvent}, NetworkDiscoveryError, }; -use crate::{peer_validator::PeerValidator, proto::rpc::GetPeersRequest, rpc, DhtConfig}; +use crate::{ + peer_validator::{PeerValidator, PeerValidatorError}, + proto::rpc::GetPeersRequest, + rpc, + DhtConfig, +}; const LOG_TARGET: &str = "comms::dht::network_discovery"; @@ -209,6 +214,7 @@ impl Discovering { self.stats.num_duplicate_peers += 1; Ok(()) }, + Err(err @ PeerValidatorError::PeerManagerError(_)) => Err(err.into()), Err(err) => { warn!( target: LOG_TARGET, diff --git a/comms/dht/src/network_discovery/test.rs b/comms/dht/src/network_discovery/test.rs index 31897a87a6..1d791d459a 100644 --- a/comms/dht/src/network_discovery/test.rs +++ b/comms/dht/src/network_discovery/test.rs @@ -151,6 +151,57 @@ mod state_machine { assert_eq!(info.sync_peers, vec![peer_node_identity.node_id().clone()]); } + #[runtime::test] + #[allow(clippy::redundant_closure)] + async fn dht_banning_peers() { + const NUM_PEERS: usize = 3; + let config = DhtConfig { + num_neighbouring_nodes: 4, + network_discovery: NetworkDiscoveryConfig { + min_desired_peers: NUM_PEERS, + ..Default::default() + }, + ..DhtConfig::default_local_test() + }; + let (discovery_actor, connectivity_mock, peer_manager, node_identity, _event_rx, _shutdown) = + setup(config, make_node_identity(), vec![]).await; + + let mock = DhtRpcServiceMock::new(); + let service = rpc::DhtService::new(mock.clone()); + let protocol_name = service.as_protocol_name(); + + let mut mock_server = MockRpcServer::new(service, node_identity.clone()); + let peer_node_identity = build_node_identity(PeerFeatures::COMMUNICATION_NODE); + // Add the peer that we'll sync from + peer_manager.add_peer(peer_node_identity.to_peer()).await.unwrap(); + mock_server.serve(); + + // Create a connection to the RPC mock and then make it available to the connectivity manager mock + let connection = mock_server + .create_connection(peer_node_identity.to_peer(), protocol_name.into()) + .await; + + connectivity_mock + .set_connectivity_status(ConnectivityStatus::Online(NUM_PEERS)) + .await; + connectivity_mock.add_active_connection(connection).await; + + // Checking banning logic + let mut invalid_peer = make_node_identity().to_peer(); + invalid_peer.set_valid_identity_signature(make_node_identity().identity_signature_read().clone().unwrap()); + let resp = GetPeersResponse { + peer: Some(invalid_peer.clone().into()), + }; + mock.get_peers.set_response(Ok(vec![resp])).await; + + discovery_actor.spawn(); + + connectivity_mock.await_call_count(1).await; + let banned = connectivity_mock.take_banned_peers().await; + let (peer, _, _) = &banned[0]; + assert_eq!(peer, peer_node_identity.node_id()); + } + #[runtime::test] async fn it_shuts_down() { let (discovery, _, _, _, _, mut shutdown) = setup(Default::default(), make_node_identity(), vec![]).await; diff --git a/integration_tests/helpers/transactionOutputHashing.js b/integration_tests/helpers/transactionOutputHashing.js index 2a2759f51c..d51178d4c9 100644 --- a/integration_tests/helpers/transactionOutputHashing.js +++ b/integration_tests/helpers/transactionOutputHashing.js @@ -41,6 +41,7 @@ const getTransactionOutputHash = function (output) { assertBufferType(output.script); assertBufferType(output.covenant); assertBufferType(output.encrypted_value, 24); + assertBufferType(output.sender_offset_public_key, 32); const hash = consensusHashers .transactionHasher("transaction_output") // version @@ -55,6 +56,8 @@ const getTransactionOutputHash = function (output) { .chain(toLengthEncoded(output.covenant)) // encrypted_value .chain(output.encrypted_value) + // sender offset public key + .chain(output.sender_offset_public_key) // minimum_value_promise .chain(toLittleEndian(output.minimum_value_promise, 64)) .finalize();