From 3a0a1aed1a64eedd4cae8350a5f408cb21f3e1b4 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Mon, 11 May 2026 20:48:27 -0500 Subject: [PATCH 01/13] Reject Txns with system as initiator --- binary_port/src/error_code.rs | 2 + node/src/components/transaction_acceptor.rs | 23 +++++++ .../components/transaction_acceptor/error.rs | 4 ++ .../components/transaction_acceptor/tests.rs | 45 +++++++++++++- storage/src/system/mint.rs | 3 - types/src/transaction/transaction_v1.rs | 62 ++++++++++++++++++- 6 files changed, 133 insertions(+), 6 deletions(-) diff --git a/binary_port/src/error_code.rs b/binary_port/src/error_code.rs index e3ea4b3a0a..70b65592f6 100644 --- a/binary_port/src/error_code.rs +++ b/binary_port/src/error_code.rs @@ -370,6 +370,8 @@ pub enum ErrorCode { InvalidDelegationAmount = 116, #[error("the transaction invocation target is unsupported under V2 runtime")] UnsupportedInvocationTarget = 117, + #[error("invalid initiator in txn")] + InvalidInitiator = 118, } impl TryFrom for ErrorCode { diff --git a/node/src/components/transaction_acceptor.rs b/node/src/components/transaction_acceptor.rs index 37caf3d38d..e4cb02388e 100644 --- a/node/src/components/transaction_acceptor.rs +++ b/node/src/components/transaction_acceptor.rs @@ -8,6 +8,7 @@ use std::{collections::BTreeSet, fmt::Debug, sync::Arc}; use casper_types::{ contracts::ProtocolVersionMajor, ContractRuntimeTag, InvalidTransaction, InvalidTransactionV1, + PublicKey, }; use datasize::DataSize; use prometheus::Registry; @@ -142,6 +143,28 @@ impl TransactionAcceptor { verification_start_timestamp, )); + match meta_transaction.initiator_addr() { + InitiatorAddr::PublicKey(initiating_public_key) => { + if initiating_public_key == &PublicKey::System { + return self.reject_transaction( + effect_builder, + *event_metadata, + Error::InvalidInitiator, + ); + } + } + InitiatorAddr::AccountHash(initiating_account_hash) => { + let system_account_hash = PublicKey::System.to_account_hash(); + if initiating_account_hash == &system_account_hash { + return self.reject_transaction( + effect_builder, + *event_metadata, + Error::InvalidInitiator, + ); + } + } + } + if meta_transaction.is_install_or_upgrade() && meta_transaction.is_v2_wasm() && meta_transaction.seed().is_none() diff --git a/node/src/components/transaction_acceptor/error.rs b/node/src/components/transaction_acceptor/error.rs index 1ce7409fcd..adf160317b 100644 --- a/node/src/components/transaction_acceptor/error.rs +++ b/node/src/components/transaction_acceptor/error.rs @@ -52,6 +52,9 @@ pub(crate) enum Error { /// Component state error: expected a version 1 transaction. #[error("internal error: expected a transaction")] ExpectedTransactionV1, + + #[error("txn with system account as inititator")] + InvalidInitiator, } impl Error { @@ -123,6 +126,7 @@ impl From for BinaryPortErrorCode { Error::InvalidTransaction(invalid_transaction) => { BinaryPortErrorCode::from(invalid_transaction) } + Error::InvalidInitiator => BinaryPortErrorCode::InvalidInitiator, } } } diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index ee77a15fd6..f959a16060 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -250,6 +250,8 @@ enum TestScenario { ContractVersionExistance, ), VmCasperV2ByPackageHash, + FromPeerWithSystemInitiator, + FromClientWithSystemInitiator, } impl TestScenario { @@ -268,7 +270,8 @@ impl TestScenario { | TestScenario::FromPeerCustomPaymentContractPackage(_) | TestScenario::FromPeerSessionContract(..) | TestScenario::FromPeerSessionContractPackage(..) - | TestScenario::InvalidFieldsFromPeer => Source::Peer(NodeId::random(rng)), + | TestScenario::InvalidFieldsFromPeer + | TestScenario::FromPeerWithSystemInitiator => Source::Peer(NodeId::random(rng)), TestScenario::FromClientInvalidTransaction(_) | TestScenario::FromClientInvalidTransactionZeroPayment(_) | TestScenario::FromClientSlightlyFutureDatedTransaction(_) @@ -305,7 +308,8 @@ impl TestScenario { | TestScenario::RedelegateExceedingMaximumDelegation | TestScenario::DelegateExceedingMaximumDelegation | TestScenario::VmCasperV2ByPackageHash - | TestScenario::V1ByPackage(..) => Source::Client, + | TestScenario::V1ByPackage(..) + | TestScenario::FromClientWithSystemInitiator => Source::Client, } } @@ -324,6 +328,17 @@ impl TestScenario { txn.invalidate(); Transaction::from(txn) } + TestScenario::FromPeerWithSystemInitiator + | TestScenario::FromClientWithSystemInitiator => { + let txn = TransactionV1::random_with_system_initiator(rng, None, None); + let cloned = txn.clone(); + assert_eq!( + cloned.initiator_addr(), + &InitiatorAddr::PublicKey(PublicKey::System) + ); + cloned.verify().expect("must verify"); + Transaction::from(txn) + } TestScenario::FromClientInvalidTransactionZeroPayment(TxnType::V1) => { let txn = TransactionV1Builder::new_session( false, @@ -937,6 +952,7 @@ impl TestScenario { HashOrName::Name => true, } }, + TestScenario::FromPeerWithSystemInitiator | TestScenario::FromClientWithSystemInitiator => false, } } @@ -1756,6 +1772,15 @@ async fn run_transaction_acceptor_without_timeout( ) ), }, + TestScenario::FromPeerWithSystemInitiator + | TestScenario::FromClientWithSystemInitiator => { + matches!( + event, + Event::TransactionAcceptorAnnouncement( + TransactionAcceptorAnnouncement::InvalidTransaction { .. } + ) + ) + } } }; runner @@ -3065,3 +3090,19 @@ async fn should_succeed_when_asking_for_active_exact_version() { .await; assert!(result.is_ok()) } + +#[tokio::test] +async fn should_reject_txn_with_system_as_initiator_from_peer() { + let scenario = TestScenario::FromPeerWithSystemInitiator; + let result = run_transaction_acceptor(scenario).await; + + assert!(matches!(result, Err(super::Error::InvalidInitiator))) +} + +#[tokio::test] +async fn should_reject_txn_with_system_as_initiator_from_client() { + let scenario = TestScenario::FromClientWithSystemInitiator; + let result = run_transaction_acceptor(scenario).await; + + assert!(matches!(result, Err(super::Error::InvalidInitiator))) +} diff --git a/storage/src/system/mint.rs b/storage/src/system/mint.rs index dbc2e5d6d0..1dffcb110d 100644 --- a/storage/src/system/mint.rs +++ b/storage/src/system/mint.rs @@ -219,9 +219,6 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { } if !source.is_writeable() || !target.is_addable() { - // TODO: I don't think we should enforce is addable on the target - // Unlike other uses of URefs (such as a counter), in this context the value represents - // a deposit of token. Generally, deposit of a desirable resource is permissive. return Err(Error::InvalidAccessRights); } let source_available_balance: U512 = match self.available_balance(source)? { diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index 41d4b7ac30..d860704e77 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -49,7 +49,7 @@ use super::{ Approval, ApprovalsHash, InitiatorAddr, PricingMode, }; #[cfg(any(feature = "std", feature = "testing", test))] -use crate::bytesrepr::Bytes; +use crate::{bytesrepr::Bytes, PublicKey}; use crate::{Digest, DisplayIter, SecretKey, TimeDiff, Timestamp}; pub use errors_v1::{ @@ -202,6 +202,38 @@ impl TransactionV1 { transaction } + #[cfg(any(feature = "std", test, feature = "testing"))] + pub(crate) fn build_with_system_initiator( + chain_name: String, + timestamp: Timestamp, + ttl: TimeDiff, + pricing_mode: PricingMode, + fields: BTreeMap, + initiator_addr_and_secret_key: InitiatorAddrAndSecretKey, + ) -> TransactionV1 { + let initiator_addr = InitiatorAddr::PublicKey(PublicKey::System); + let transaction_v1_payload = TransactionV1Payload::new( + chain_name, + timestamp, + ttl, + pricing_mode, + initiator_addr, + fields, + ); + let hash = Digest::hash( + transaction_v1_payload + .to_bytes() + .unwrap_or_else(|error| panic!("should serialize body: {}", error)), + ); + let mut transaction = + TransactionV1::new(hash.into(), transaction_v1_payload, BTreeSet::new()); + + if let Some(secret_key) = initiator_addr_and_secret_key.secret_key() { + transaction.sign(secret_key); + } + transaction + } + /// Adds a signature of this transaction's hash to its approvals. pub fn sign(&mut self, secret_key: &SecretKey) { let approval = Approval::create(&self.hash.into(), secret_key); @@ -332,6 +364,34 @@ impl TransactionV1 { ) } + #[cfg(any(all(feature = "std", feature = "testing"), test))] + pub fn random_with_system_initiator( + rng: &mut TestRng, + maybe_timestamp: Option, + ttl: Option, + ) -> Self { + let secret_key = SecretKey::random(rng); + let timestamp = maybe_timestamp.unwrap_or_else(Timestamp::now); + let ttl_millis = ttl.map_or( + rng.gen_range(60_000..TransactionConfig::default().max_ttl.millis()), + |ttl| ttl.millis(), + ); + let container = FieldsContainer::random_of_lane(rng, MINT_LANE_ID); + let initiator_addr_and_secret_key = InitiatorAddrAndSecretKey::SecretKey(&secret_key); + let pricing_mode = PricingMode::Fixed { + gas_price_tolerance: 5, + additional_computation_factor: 0, + }; + TransactionV1::build_with_system_initiator( + rng.random_string(5..10), + timestamp, + TimeDiff::from_millis(ttl_millis), + pricing_mode, + container.to_map().unwrap(), + initiator_addr_and_secret_key, + ) + } + #[cfg(any(all(feature = "std", feature = "testing"), test))] pub fn random_with_timestamp_and_ttl( rng: &mut TestRng, From 965ed9384a8adfaba807a6958d69987734ec08ee Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 08:03:34 -0500 Subject: [PATCH 02/13] Address PR feedback --- .../components/transaction_acceptor/tests.rs | 62 +++++++++++++------ types/src/transaction/transaction_v1.rs | 9 ++- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index f959a16060..d71d32cd24 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -250,8 +250,11 @@ enum TestScenario { ContractVersionExistance, ), VmCasperV2ByPackageHash, - FromPeerWithSystemInitiator, - FromClientWithSystemInitiator, + // For both these scenarios, + // true means use public key + // false means use account hash + FromPeerWithSystemInitiator(bool), + FromClientWithSystemInitiator(bool), } impl TestScenario { @@ -271,7 +274,7 @@ impl TestScenario { | TestScenario::FromPeerSessionContract(..) | TestScenario::FromPeerSessionContractPackage(..) | TestScenario::InvalidFieldsFromPeer - | TestScenario::FromPeerWithSystemInitiator => Source::Peer(NodeId::random(rng)), + | TestScenario::FromPeerWithSystemInitiator(_) => Source::Peer(NodeId::random(rng)), TestScenario::FromClientInvalidTransaction(_) | TestScenario::FromClientInvalidTransactionZeroPayment(_) | TestScenario::FromClientSlightlyFutureDatedTransaction(_) @@ -309,7 +312,7 @@ impl TestScenario { | TestScenario::DelegateExceedingMaximumDelegation | TestScenario::VmCasperV2ByPackageHash | TestScenario::V1ByPackage(..) - | TestScenario::FromClientWithSystemInitiator => Source::Client, + | TestScenario::FromClientWithSystemInitiator(_) => Source::Client, } } @@ -328,14 +331,21 @@ impl TestScenario { txn.invalidate(); Transaction::from(txn) } - TestScenario::FromPeerWithSystemInitiator - | TestScenario::FromClientWithSystemInitiator => { - let txn = TransactionV1::random_with_system_initiator(rng, None, None); + TestScenario::FromPeerWithSystemInitiator(should_use_public_key) + | TestScenario::FromClientWithSystemInitiator(should_use_public_key) => { + let txn = TransactionV1::random_with_system_initiator(rng, *should_use_public_key, None, None); let cloned = txn.clone(); - assert_eq!( - cloned.initiator_addr(), - &InitiatorAddr::PublicKey(PublicKey::System) - ); + if *should_use_public_key { + assert_eq!( + cloned.initiator_addr(), + &InitiatorAddr::PublicKey(PublicKey::System) + ) + } else { + assert_eq!( + cloned.initiator_addr(), + &InitiatorAddr::AccountHash(PublicKey::System.to_account_hash()) + ) + }; cloned.verify().expect("must verify"); Transaction::from(txn) } @@ -952,7 +962,7 @@ impl TestScenario { HashOrName::Name => true, } }, - TestScenario::FromPeerWithSystemInitiator | TestScenario::FromClientWithSystemInitiator => false, + TestScenario::FromPeerWithSystemInitiator(_) | TestScenario::FromClientWithSystemInitiator(_) => false, } } @@ -1772,8 +1782,8 @@ async fn run_transaction_acceptor_without_timeout( ) ), }, - TestScenario::FromPeerWithSystemInitiator - | TestScenario::FromClientWithSystemInitiator => { + TestScenario::FromPeerWithSystemInitiator(_) + | TestScenario::FromClientWithSystemInitiator(_) => { matches!( event, Event::TransactionAcceptorAnnouncement( @@ -3092,17 +3102,33 @@ async fn should_succeed_when_asking_for_active_exact_version() { } #[tokio::test] -async fn should_reject_txn_with_system_as_initiator_from_peer() { - let scenario = TestScenario::FromPeerWithSystemInitiator; +async fn should_reject_txn_with_system_public_key_as_initiator_from_peer() { + let scenario = TestScenario::FromPeerWithSystemInitiator(true); + let result = run_transaction_acceptor(scenario).await; + + assert!(matches!(result, Err(super::Error::InvalidInitiator))) +} + +#[tokio::test] +async fn should_reject_txn_with_system_public_key_as_initiator_from_client() { + let scenario = TestScenario::FromClientWithSystemInitiator(true); let result = run_transaction_acceptor(scenario).await; assert!(matches!(result, Err(super::Error::InvalidInitiator))) } #[tokio::test] -async fn should_reject_txn_with_system_as_initiator_from_client() { - let scenario = TestScenario::FromClientWithSystemInitiator; +async fn should_reject_txn_with_system_account_hash_as_initiator_from_peer() { + let scenario = TestScenario::FromPeerWithSystemInitiator(false); let result = run_transaction_acceptor(scenario).await; assert!(matches!(result, Err(super::Error::InvalidInitiator))) } + +#[tokio::test] +async fn should_reject_txn_with_system_account_hash_as_initiator_from_client() { + let scenario = TestScenario::FromClientWithSystemInitiator(false); + let result = run_transaction_acceptor(scenario).await; + + assert!(matches!(result, Err(super::Error::InvalidInitiator))) +} \ No newline at end of file diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index d860704e77..a9574d931f 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -209,9 +209,14 @@ impl TransactionV1 { ttl: TimeDiff, pricing_mode: PricingMode, fields: BTreeMap, + should_use_public_key: bool, initiator_addr_and_secret_key: InitiatorAddrAndSecretKey, ) -> TransactionV1 { - let initiator_addr = InitiatorAddr::PublicKey(PublicKey::System); + let initiator_addr = if should_use_public_key { + InitiatorAddr::PublicKey(PublicKey::System) + } else { + InitiatorAddr::AccountHash(PublicKey::System.to_account_hash()) + }; let transaction_v1_payload = TransactionV1Payload::new( chain_name, timestamp, @@ -367,6 +372,7 @@ impl TransactionV1 { #[cfg(any(all(feature = "std", feature = "testing"), test))] pub fn random_with_system_initiator( rng: &mut TestRng, + should_use_public_key: bool, maybe_timestamp: Option, ttl: Option, ) -> Self { @@ -388,6 +394,7 @@ impl TransactionV1 { TimeDiff::from_millis(ttl_millis), pricing_mode, container.to_map().unwrap(), + should_use_public_key, initiator_addr_and_secret_key, ) } From 8d4a8af10dea78a61db1d44d3fc00053b9db447f Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 08:46:21 -0500 Subject: [PATCH 03/13] Run make format --- node/src/components/transaction_acceptor/tests.rs | 13 +++++++++---- types/src/transaction/transaction_v1.rs | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index d71d32cd24..68c13fd2af 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -250,7 +250,7 @@ enum TestScenario { ContractVersionExistance, ), VmCasperV2ByPackageHash, - // For both these scenarios, + // For both these scenarios, // true means use public key // false means use account hash FromPeerWithSystemInitiator(bool), @@ -333,14 +333,19 @@ impl TestScenario { } TestScenario::FromPeerWithSystemInitiator(should_use_public_key) | TestScenario::FromClientWithSystemInitiator(should_use_public_key) => { - let txn = TransactionV1::random_with_system_initiator(rng, *should_use_public_key, None, None); + let txn = TransactionV1::random_with_system_initiator( + rng, + *should_use_public_key, + None, + None, + ); let cloned = txn.clone(); if *should_use_public_key { assert_eq!( cloned.initiator_addr(), &InitiatorAddr::PublicKey(PublicKey::System) ) - } else { + } else { assert_eq!( cloned.initiator_addr(), &InitiatorAddr::AccountHash(PublicKey::System.to_account_hash()) @@ -3131,4 +3136,4 @@ async fn should_reject_txn_with_system_account_hash_as_initiator_from_client() { let result = run_transaction_acceptor(scenario).await; assert!(matches!(result, Err(super::Error::InvalidInitiator))) -} \ No newline at end of file +} diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index a9574d931f..88a64a17ba 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -209,10 +209,10 @@ impl TransactionV1 { ttl: TimeDiff, pricing_mode: PricingMode, fields: BTreeMap, - should_use_public_key: bool, + should_use_public_key: bool, initiator_addr_and_secret_key: InitiatorAddrAndSecretKey, ) -> TransactionV1 { - let initiator_addr = if should_use_public_key { + let initiator_addr = if should_use_public_key { InitiatorAddr::PublicKey(PublicKey::System) } else { InitiatorAddr::AccountHash(PublicKey::System.to_account_hash()) From e3dacada800c462ef64ad1d7d8d89a779e95b6f8 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 12:58:18 -0500 Subject: [PATCH 04/13] Push system initiator checks into txns --- binary_port/src/error_code.rs | 2 -- node/src/components/transaction_acceptor.rs | 23 -------------- .../components/transaction_acceptor/error.rs | 3 -- .../components/transaction_acceptor/tests.rs | 30 ++++++++++++++++--- .../meta_transaction/meta_transaction_v1.rs | 17 +++++++++-- types/src/transaction/deploy.rs | 4 +++ types/src/transaction/deploy/error.rs | 7 ++++- types/src/transaction/transaction_v1.rs | 9 +++--- .../transaction/transaction_v1/errors_v1.rs | 9 +++++- 9 files changed, 64 insertions(+), 40 deletions(-) diff --git a/binary_port/src/error_code.rs b/binary_port/src/error_code.rs index 70b65592f6..e3ea4b3a0a 100644 --- a/binary_port/src/error_code.rs +++ b/binary_port/src/error_code.rs @@ -370,8 +370,6 @@ pub enum ErrorCode { InvalidDelegationAmount = 116, #[error("the transaction invocation target is unsupported under V2 runtime")] UnsupportedInvocationTarget = 117, - #[error("invalid initiator in txn")] - InvalidInitiator = 118, } impl TryFrom for ErrorCode { diff --git a/node/src/components/transaction_acceptor.rs b/node/src/components/transaction_acceptor.rs index e4cb02388e..37caf3d38d 100644 --- a/node/src/components/transaction_acceptor.rs +++ b/node/src/components/transaction_acceptor.rs @@ -8,7 +8,6 @@ use std::{collections::BTreeSet, fmt::Debug, sync::Arc}; use casper_types::{ contracts::ProtocolVersionMajor, ContractRuntimeTag, InvalidTransaction, InvalidTransactionV1, - PublicKey, }; use datasize::DataSize; use prometheus::Registry; @@ -143,28 +142,6 @@ impl TransactionAcceptor { verification_start_timestamp, )); - match meta_transaction.initiator_addr() { - InitiatorAddr::PublicKey(initiating_public_key) => { - if initiating_public_key == &PublicKey::System { - return self.reject_transaction( - effect_builder, - *event_metadata, - Error::InvalidInitiator, - ); - } - } - InitiatorAddr::AccountHash(initiating_account_hash) => { - let system_account_hash = PublicKey::System.to_account_hash(); - if initiating_account_hash == &system_account_hash { - return self.reject_transaction( - effect_builder, - *event_metadata, - Error::InvalidInitiator, - ); - } - } - } - if meta_transaction.is_install_or_upgrade() && meta_transaction.is_v2_wasm() && meta_transaction.seed().is_none() diff --git a/node/src/components/transaction_acceptor/error.rs b/node/src/components/transaction_acceptor/error.rs index adf160317b..c0a66afa48 100644 --- a/node/src/components/transaction_acceptor/error.rs +++ b/node/src/components/transaction_acceptor/error.rs @@ -53,8 +53,6 @@ pub(crate) enum Error { #[error("internal error: expected a transaction")] ExpectedTransactionV1, - #[error("txn with system account as inititator")] - InvalidInitiator, } impl Error { @@ -126,7 +124,6 @@ impl From for BinaryPortErrorCode { Error::InvalidTransaction(invalid_transaction) => { BinaryPortErrorCode::from(invalid_transaction) } - Error::InvalidInitiator => BinaryPortErrorCode::InvalidInitiator, } } } diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index 68c13fd2af..d99ba3df64 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -3111,7 +3111,12 @@ async fn should_reject_txn_with_system_public_key_as_initiator_from_peer() { let scenario = TestScenario::FromPeerWithSystemInitiator(true); let result = run_transaction_acceptor(scenario).await; - assert!(matches!(result, Err(super::Error::InvalidInitiator))) + assert!(matches!( + result, + Err(super::Error::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::InvalidInitiator + ))) + )) } #[tokio::test] @@ -3119,7 +3124,13 @@ async fn should_reject_txn_with_system_public_key_as_initiator_from_client() { let scenario = TestScenario::FromClientWithSystemInitiator(true); let result = run_transaction_acceptor(scenario).await; - assert!(matches!(result, Err(super::Error::InvalidInitiator))) + assert!(matches!( + result, + Err(super::Error::Parameters { + failure: ParameterFailure::InvalidAssociatedKeys { .. }, + .. + }) + )) } #[tokio::test] @@ -3127,7 +3138,12 @@ async fn should_reject_txn_with_system_account_hash_as_initiator_from_peer() { let scenario = TestScenario::FromPeerWithSystemInitiator(false); let result = run_transaction_acceptor(scenario).await; - assert!(matches!(result, Err(super::Error::InvalidInitiator))) + assert!(matches!( + result, + Err(super::Error::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::InvalidInitiator + ))) + )) } #[tokio::test] @@ -3135,5 +3151,11 @@ async fn should_reject_txn_with_system_account_hash_as_initiator_from_client() { let scenario = TestScenario::FromClientWithSystemInitiator(false); let result = run_transaction_acceptor(scenario).await; - assert!(matches!(result, Err(super::Error::InvalidInitiator))) + assert!(matches!( + result, + Err(super::Error::Parameters { + failure: ParameterFailure::InvalidAssociatedKeys { .. }, + .. + }) + )) } diff --git a/node/src/types/transaction/meta_transaction/meta_transaction_v1.rs b/node/src/types/transaction/meta_transaction/meta_transaction_v1.rs index 09abc0c4d8..464e7f5a14 100644 --- a/node/src/types/transaction/meta_transaction/meta_transaction_v1.rs +++ b/node/src/types/transaction/meta_transaction/meta_transaction_v1.rs @@ -2,8 +2,8 @@ use crate::types::transaction::arg_handling; use casper_types::{ bytesrepr::ToBytes, calculate_transaction_lane, crypto, Approval, Chainspec, ContractRuntimeTag, Digest, DisplayIter, Gas, HashAddr, InitiatorAddr, InvalidTransaction, - InvalidTransactionV1, PricingHandling, PricingMode, TimeDiff, Timestamp, TransactionArgs, - TransactionConfig, TransactionEntryPoint, TransactionInvocationTarget, + InvalidTransactionV1, PricingHandling, PricingMode, PublicKey, TimeDiff, Timestamp, + TransactionArgs, TransactionConfig, TransactionEntryPoint, TransactionInvocationTarget, TransactionRuntimeParams, TransactionScheduling, TransactionTarget, TransactionV1, TransactionV1Config, TransactionV1ExcessiveSizeError, TransactionV1Hash, AUCTION_LANE_ID, MINT_LANE_ID, U512, @@ -228,6 +228,19 @@ impl MetaTransactionV1 { return Err(InvalidTransactionV1::EmptyApprovals); } + match &self.initiator_addr { + InitiatorAddr::PublicKey(public_key) => { + if public_key == &PublicKey::System { + return Err(InvalidTransactionV1::InvalidInitiator); + } + } + InitiatorAddr::AccountHash(account_hash) => { + if account_hash == &PublicKey::System.to_account_hash() { + return Err(InvalidTransactionV1::InvalidInitiator); + } + } + } + self.has_valid_hash().clone()?; for (index, approval) in self.approvals.iter().enumerate() { diff --git a/types/src/transaction/deploy.rs b/types/src/transaction/deploy.rs index a9a7609e94..919e4d6e91 100644 --- a/types/src/transaction/deploy.rs +++ b/types/src/transaction/deploy.rs @@ -1714,6 +1714,10 @@ fn validate_deploy(deploy: &Deploy) -> Result<(), InvalidDeploy> { return Err(InvalidDeploy::EmptyApprovals); } + if deploy.header().account() == &PublicKey::System { + return Err(InvalidDeploy::InvalidInitiator); + } + deploy.has_valid_hash()?; for (index, approval) in deploy.approvals.iter().enumerate() { diff --git a/types/src/transaction/deploy/error.rs b/types/src/transaction/deploy/error.rs index 14ca089463..3aa6eee3ea 100644 --- a/types/src/transaction/deploy/error.rs +++ b/types/src/transaction/deploy/error.rs @@ -161,6 +161,9 @@ pub enum InvalidDeploy { /// Pricing mode not supported PricingModeNotSupported, + + /// Invalid initiator for the deploy + InvalidInitiator, } impl Display for InvalidDeploy { @@ -302,6 +305,7 @@ impl Display for InvalidDeploy { } InvalidDeploy::InvalidPaymentAmount => write!(formatter, "invalid payment amount",), InvalidDeploy::PricingModeNotSupported => write!(formatter, "pricing mode not supported",), + InvalidDeploy::InvalidInitiator => write!(formatter, "invalid initiator") } } } @@ -342,7 +346,8 @@ impl StdError for InvalidDeploy { | InvalidDeploy::NoLaneMatch | InvalidDeploy::ExceededLaneGasLimit { .. } | InvalidDeploy::InvalidPaymentAmount - | InvalidDeploy::PricingModeNotSupported => None, + | InvalidDeploy::PricingModeNotSupported + | InvalidDeploy::InvalidInitiator => None, } } } diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index 88a64a17ba..99cb392117 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -384,12 +384,13 @@ impl TransactionV1 { ); let container = FieldsContainer::random_of_lane(rng, MINT_LANE_ID); let initiator_addr_and_secret_key = InitiatorAddrAndSecretKey::SecretKey(&secret_key); - let pricing_mode = PricingMode::Fixed { - gas_price_tolerance: 5, - additional_computation_factor: 0, + let pricing_mode = PricingMode::PaymentLimited { + payment_amount: 10_000_000_000u64, + gas_price_tolerance: 1, + standard_payment: false, }; TransactionV1::build_with_system_initiator( - rng.random_string(5..10), + "casper-example".to_string(), timestamp, TimeDiff::from_millis(ttl_millis), pricing_mode, diff --git a/types/src/transaction/transaction_v1/errors_v1.rs b/types/src/transaction/transaction_v1/errors_v1.rs index 814803c168..917c96b873 100644 --- a/types/src/transaction/transaction_v1/errors_v1.rs +++ b/types/src/transaction/transaction_v1/errors_v1.rs @@ -282,6 +282,9 @@ pub enum InvalidTransaction { UnsupportedInvocationTarget { id: Option, }, + + /// Invalid initiator for the transaction. + InvalidInitiator, } impl Display for InvalidTransaction { @@ -527,6 +530,9 @@ impl Display for InvalidTransaction { "the transaction invocation target is unsupported under V2 runtime", ) } + InvalidTransaction::InvalidInitiator => { + write!(formatter, "the transaction has an invalid initiator") + } } } } @@ -589,7 +595,8 @@ impl StdError for InvalidTransaction { | InvalidTransaction::InvalidMaximumDelegationAmount { .. } | InvalidTransaction::InvalidReservedSlots { .. } | InvalidTransaction::InvalidDelegationAmount { .. } - | InvalidTransaction::UnsupportedInvocationTarget { .. } => None, + | InvalidTransaction::UnsupportedInvocationTarget { .. } + | InvalidTransaction::InvalidInitiator => None, } } } From 6eb5c621e62de86d3d4513ff5266f8c6bf8aa306 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 12:58:44 -0500 Subject: [PATCH 05/13] Run make format --- node/src/components/transaction_acceptor/error.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/node/src/components/transaction_acceptor/error.rs b/node/src/components/transaction_acceptor/error.rs index c0a66afa48..1ce7409fcd 100644 --- a/node/src/components/transaction_acceptor/error.rs +++ b/node/src/components/transaction_acceptor/error.rs @@ -52,7 +52,6 @@ pub(crate) enum Error { /// Component state error: expected a version 1 transaction. #[error("internal error: expected a transaction")] ExpectedTransactionV1, - } impl Error { From 2eef2f1c4fa3dd0513c39485a83d04ea58b57c09 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 13:14:45 -0500 Subject: [PATCH 06/13] Expand checks for txns --- node/src/components/transaction_acceptor/tests.rs | 1 - types/src/transaction/transaction_v1.rs | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index d99ba3df64..a1e05d1d01 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -351,7 +351,6 @@ impl TestScenario { &InitiatorAddr::AccountHash(PublicKey::System.to_account_hash()) ) }; - cloned.verify().expect("must verify"); Transaction::from(txn) } TestScenario::FromClientInvalidTransactionZeroPayment(TxnType::V1) => { diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index 99cb392117..2fca1d51d2 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -511,6 +511,19 @@ impl TransactionV1 { return Err(InvalidTransactionV1::EmptyApprovals); } + match &self.initiator_addr() { + InitiatorAddr::PublicKey(public_key) => { + if public_key == &PublicKey::System { + return Err(InvalidTransactionV1::InvalidInitiator); + } + } + InitiatorAddr::AccountHash(account_hash) => { + if account_hash == &PublicKey::System.to_account_hash() { + return Err(InvalidTransactionV1::InvalidInitiator); + } + } + } + self.has_valid_hash()?; for (index, approval) in self.approvals.iter().enumerate() { From f7b7de66c58afff9a460fc0d8e0d3228ccedb4bf Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 13:15:39 -0500 Subject: [PATCH 07/13] Run make format --- types/src/transaction/transaction_v1.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index 2fca1d51d2..c75f37160c 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -523,7 +523,7 @@ impl TransactionV1 { } } } - + self.has_valid_hash()?; for (index, approval) in self.approvals.iter().enumerate() { From 5aed85c99215a0b3418e5bbf3c51abe49ef2f3d0 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 13:47:05 -0500 Subject: [PATCH 08/13] Address CI issues --- types/src/transaction/transaction_v1.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index c75f37160c..79ecca23da 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -48,8 +48,9 @@ use super::{ serialization::{CalltableSerializationEnvelope, CalltableSerializationEnvelopeBuilder}, Approval, ApprovalsHash, InitiatorAddr, PricingMode, }; +use crate::PublicKey; #[cfg(any(feature = "std", feature = "testing", test))] -use crate::{bytesrepr::Bytes, PublicKey}; +use crate::{bytesrepr::Bytes}; use crate::{Digest, DisplayIter, SecretKey, TimeDiff, Timestamp}; pub use errors_v1::{ From 6f8a2464179da1e3886de41db3333ffc4487cb03 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 13:55:15 -0500 Subject: [PATCH 09/13] Version bump to 2.2.1 --- Cargo.lock | 6 +++--- binary_port/Cargo.toml | 4 ++-- execution_engine/Cargo.toml | 2 +- execution_engine_testing/test_support/Cargo.toml | 4 ++-- executor/wasm/Cargo.toml | 2 +- executor/wasm_host/Cargo.toml | 2 +- executor/wasm_interface/Cargo.toml | 2 +- executor/wasmer_backend/Cargo.toml | 2 +- node/Cargo.toml | 8 ++++---- node/src/lib.rs | 2 +- smart_contracts/contract/Cargo.toml | 2 +- storage/Cargo.toml | 2 +- types/Cargo.toml | 2 +- types/src/lib.rs | 2 +- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c70166f76f..0cfb8b8fdd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -682,7 +682,7 @@ dependencies = [ [[package]] name = "casper-binary-port" -version = "1.1.1" +version = "1.2.0" dependencies = [ "bincode", "bytes", @@ -974,7 +974,7 @@ dependencies = [ [[package]] name = "casper-node" -version = "2.2.0" +version = "2.2.1" dependencies = [ "ansi_term", "anyhow", @@ -1105,7 +1105,7 @@ dependencies = [ [[package]] name = "casper-types" -version = "7.0.0" +version = "7.1.0" dependencies = [ "base16", "base64 0.13.1", diff --git a/binary_port/Cargo.toml b/binary_port/Cargo.toml index f98d07032a..fb1c388363 100644 --- a/binary_port/Cargo.toml +++ b/binary_port/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casper-binary-port" -version = "1.1.1" +version = "1.2.0" edition = "2018" description = "Types for the casper node binary port" documentation = "https://docs.rs/casper-binary-port" @@ -13,7 +13,7 @@ exclude = ["proptest-regressions"] [dependencies] bincode = "1.3.3" bytes = "1.0.1" -casper-types = { version = "7.0.0", path = "../types", features = ["datasize", "json-schema", "std"] } +casper-types = { version = "7.1.0", path = "../types", features = ["datasize", "json-schema", "std"] } num-derive = { workspace = true } num-traits = { workspace = true } once_cell = { version = "1.5.2" } diff --git a/execution_engine/Cargo.toml b/execution_engine/Cargo.toml index 6871568866..e801c01629 100644 --- a/execution_engine/Cargo.toml +++ b/execution_engine/Cargo.toml @@ -18,7 +18,7 @@ blake2 = { version = "0.10.6", default-features = false } blake3 = { version = "1.5.0", default-features = false, features = ["pure"] } sha2 = { version = "0.10.8", default-features = false } casper-storage = { version = "5.0.0", path = "../storage", default-features = true } -casper-types = { version = "7.0.0", path = "../types", default-features = false, features = ["datasize", "gens", "json-schema", "std"] } +casper-types = { version = "7.1.0", path = "../types", default-features = false, features = ["datasize", "gens", "json-schema", "std"] } casper-wasm = { version = "1.0.0", default-features = false, features = ["sign_ext", "call_indirect_overlong"] } casper-wasm-utils = { version = "4.0.0", default-features = false, features = ["sign_ext", "call_indirect_overlong"] } casper-wasmi = { version = "1.0.0", features = ["sign_ext", "call_indirect_overlong"] } diff --git a/execution_engine_testing/test_support/Cargo.toml b/execution_engine_testing/test_support/Cargo.toml index c597633c61..494f0571f5 100644 --- a/execution_engine_testing/test_support/Cargo.toml +++ b/execution_engine_testing/test_support/Cargo.toml @@ -13,7 +13,7 @@ license = "Apache-2.0" [dependencies] blake2 = "0.9.0" casper-storage = { version = "5.0.0", path = "../../storage" } -casper-types = { version = "7.0.0", path = "../../types" } +casper-types = { version = "7.1.0", path = "../../types" } env_logger = "0.10.0" casper-execution-engine = { version = "9.0.0", path = "../../execution_engine", features = ["test-support"] } humantime = "2" @@ -29,7 +29,7 @@ tempfile = "3.4.0" toml = "0.5.6" [dev-dependencies] -casper-types = { version = "7.0.0", path = "../../types", features = ["std"] } +casper-types = { version = "7.1.0", path = "../../types", features = ["std"] } version-sync = "0.9.3" [build-dependencies] diff --git a/executor/wasm/Cargo.toml b/executor/wasm/Cargo.toml index 698f70a837..59087b2f4e 100644 --- a/executor/wasm/Cargo.toml +++ b/executor/wasm/Cargo.toml @@ -17,7 +17,7 @@ casper-executor-wasm-host = { version = "0.1.3", path = "../wasm_host" } casper-executor-wasm-interface = { version = "0.1.3", path = "../wasm_interface" } casper-executor-wasmer-backend = { version = "0.1.3", path = "../wasmer_backend" } casper-storage = { version = "5.0.0", path = "../../storage" } -casper-types = { version = "7.0.0", path = "../../types", features = ["std"] } +casper-types = { version = "7.1.0", path = "../../types", features = ["std"] } casper-execution-engine = { version = "9.0.0", path = "../../execution_engine", features = [ "test-support", ] } diff --git a/executor/wasm_host/Cargo.toml b/executor/wasm_host/Cargo.toml index 52c5633cb2..448f1ed22d 100644 --- a/executor/wasm_host/Cargo.toml +++ b/executor/wasm_host/Cargo.toml @@ -14,7 +14,7 @@ bytes = "1.10" casper-executor-wasm-common = { version = "0.1.3", path = "../wasm_common" } casper-executor-wasm-interface = { version = "0.1.3", path = "../wasm_interface" } casper-storage = { version = "5.0.0", path = "../../storage" } -casper-types = { version = "7.0.0", path = "../../types" } +casper-types = { version = "7.1.0", path = "../../types" } either = "1.15" num-derive = { workspace = true } num-traits = { workspace = true } diff --git a/executor/wasm_interface/Cargo.toml b/executor/wasm_interface/Cargo.toml index ef8596da01..60377d71d4 100644 --- a/executor/wasm_interface/Cargo.toml +++ b/executor/wasm_interface/Cargo.toml @@ -13,6 +13,6 @@ bytes = "1.10" borsh = { version = "1.5", features = ["derive"] } casper-executor-wasm-common = { version = "0.1.3", path = "../wasm_common" } casper-storage = { version = "5.0.0", path = "../../storage" } -casper-types = { version = "7.0.0", path = "../../types" } +casper-types = { version = "7.1.0", path = "../../types" } parking_lot = "0.12" thiserror = "2" diff --git a/executor/wasmer_backend/Cargo.toml b/executor/wasmer_backend/Cargo.toml index 708f764ff0..89bd2ac66f 100644 --- a/executor/wasmer_backend/Cargo.toml +++ b/executor/wasmer_backend/Cargo.toml @@ -15,7 +15,7 @@ casper-executor-wasm-interface = { version = "0.1.3", path = "../wasm_interface" casper-executor-wasm-host = { version = "0.1.0", path = "../wasm_host" } casper-storage = { version = "5.0.0", path = "../../storage" } casper-contract-sdk-sys = { version = "0.1.3", path = "../../smart_contracts/sdk_sys" } -casper-types = { version = "7.0.0", path = "../../types" } +casper-types = { version = "7.1.0", path = "../../types" } regex = "1.11" wasmer = { version = "5.0.4", default-features = false, features = [ "singlepass", diff --git a/node/Cargo.toml b/node/Cargo.toml index ec76950f4b..30e1683f7b 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casper-node" -version = "2.2.0" # when updating, also update 'html_root_url' in lib.rs +version = "2.2.1" # when updating, also update 'html_root_url' in lib.rs authors = ["Ed Hastings ", "Karan Dhareshwar "] edition = "2021" description = "The Casper blockchain node" @@ -22,9 +22,9 @@ base16 = "0.2.1" base64 = "0.13.0" bincode = "1" bytes = "1.11.0" -casper-binary-port = { version = "1.1.1", path = "../binary_port" } +casper-binary-port = { version = "1.2.0", path = "../binary_port" } casper-storage = { version = "5.0.0", path = "../storage" } -casper-types = { version = "7.0.0", path = "../types", features = ["datasize", "json-schema", "std-fs-io"] } +casper-types = { version = "7.1.0", path = "../types", features = ["datasize", "json-schema", "std-fs-io"] } casper-execution-engine = { version = "9.0.0", path = "../execution_engine" } datasize = { version = "0.2.11", features = ["detailed", "fake_clock-types", "futures-types", "smallvec-types"] } derive_more = "0.99.7" @@ -99,7 +99,7 @@ casper-executor-wasm-interface = { version = "0.1.3", path = "../executor/wasm_i fs_extra = "1.3.0" [dev-dependencies] -casper-binary-port = { version = "1.1.1", path = "../binary_port", features = ["testing"] } +casper-binary-port = { version = "1.2.0", path = "../binary_port", features = ["testing"] } assert-json-diff = "2.0.1" assert_matches = "1.5.0" casper-types = { path = "../types", features = ["datasize", "json-schema", "std-fs-io", "testing"] } diff --git a/node/src/lib.rs b/node/src/lib.rs index 723014ce4e..4b2460a6f2 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -8,7 +8,7 @@ //! While the [`main`](fn.main.html) function is the central entrypoint for the node application, //! its core event loop is found inside the [reactor](reactor/index.html). -#![doc(html_root_url = "https://docs.rs/casper-node/2.2.0")] +#![doc(html_root_url = "https://docs.rs/casper-node/2.2.1")] #![doc( html_favicon_url = "https://raw.githubusercontent.com/casper-network/casper-node/blob/dev/images/Casper_Logo_Favicon_48.png", html_logo_url = "https://raw.githubusercontent.com/casper-network/casper-node/blob/dev/images/Casper_Logo_Favicon.png", diff --git a/smart_contracts/contract/Cargo.toml b/smart_contracts/contract/Cargo.toml index 618ab90884..84fc4d262d 100644 --- a/smart_contracts/contract/Cargo.toml +++ b/smart_contracts/contract/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/casper-network/casper-node/tree/master/smart_co license = "Apache-2.0" [dependencies] -casper-types = { version = "7.0.0", path = "../../types" } +casper-types = { version = "7.1.0", path = "../../types" } hex_fmt = "0.3.0" version-sync = { version = "0.9", optional = true } wee_alloc = { version = "0.4.5", optional = true } diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 39b141f0ea..2ea637afb3 100644 --- a/storage/Cargo.toml +++ b/storage/Cargo.toml @@ -12,7 +12,7 @@ license = "Apache-2.0" [dependencies] bincode = "1.3.1" -casper-types = { version = "7.0.0", path = "../types", features = ["datasize", "json-schema", "std"] } +casper-types = { version = "7.1.0", path = "../types", features = ["datasize", "json-schema", "std"] } datasize = "0.2.4" either = "1.8.1" lmdb-rkv = "0.14" diff --git a/types/Cargo.toml b/types/Cargo.toml index 0c72a916c5..aeb28fc3e4 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casper-types" -version = "7.0.0" # when updating, also update 'html_root_url' in lib.rs +version = "7.1.0" # when updating, also update 'html_root_url' in lib.rs authors = ["Ed Hastings "] edition = "2021" description = "Types shared by many casper crates for use on the Casper network." diff --git a/types/src/lib.rs b/types/src/lib.rs index 5b038d9f21..75611f7997 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -10,7 +10,7 @@ )), no_std )] -#![doc(html_root_url = "https://docs.rs/casper-types/7.0.0")] +#![doc(html_root_url = "https://docs.rs/casper-types/7.1.0")] #![doc( html_favicon_url = "https://raw.githubusercontent.com/casper-network/casper-node/blob/dev/images/Casper_Logo_Favicon_48.png", html_logo_url = "https://raw.githubusercontent.com/casper-network/casper-node/blob/dev/images/Casper_Logo_Favicon.png" From 746c8a92a7d77009e2ea145589dfe100156cbe61 Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 15:32:10 -0500 Subject: [PATCH 10/13] Address error code tests --- binary_port/src/error_code.rs | 4 ++++ types/src/transaction/transaction_v1.rs | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/binary_port/src/error_code.rs b/binary_port/src/error_code.rs index e3ea4b3a0a..983c54bc5f 100644 --- a/binary_port/src/error_code.rs +++ b/binary_port/src/error_code.rs @@ -370,6 +370,8 @@ pub enum ErrorCode { InvalidDelegationAmount = 116, #[error("the transaction invocation target is unsupported under V2 runtime")] UnsupportedInvocationTarget = 117, + #[error("the transaction contained an invalid initiator")] + InvalidInitiator } impl TryFrom for ErrorCode { @@ -454,6 +456,7 @@ impl From for ErrorCode { } InvalidDeploy::InvalidPaymentAmount => ErrorCode::InvalidDeployInvalidPaymentAmount, InvalidDeploy::PricingModeNotSupported => ErrorCode::PricingModeNotSupported, + InvalidDeploy::InvalidInitiator => ErrorCode::InvalidInitiator, _ => ErrorCode::InvalidDeployUnspecified, } } @@ -571,6 +574,7 @@ impl From for ErrorCode { InvalidTransactionV1::UnsupportedInvocationTarget { .. } => { ErrorCode::UnsupportedInvocationTarget } + InvalidTransactionV1::InvalidInitiator => ErrorCode::InvalidInitiator, _other => ErrorCode::InvalidTransactionUnspecified, } } diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index 79ecca23da..f7347ef809 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -48,10 +48,9 @@ use super::{ serialization::{CalltableSerializationEnvelope, CalltableSerializationEnvelopeBuilder}, Approval, ApprovalsHash, InitiatorAddr, PricingMode, }; -use crate::PublicKey; #[cfg(any(feature = "std", feature = "testing", test))] -use crate::{bytesrepr::Bytes}; -use crate::{Digest, DisplayIter, SecretKey, TimeDiff, Timestamp}; +use crate::bytesrepr::Bytes; +use crate::{Digest, DisplayIter, PublicKey, SecretKey, TimeDiff, Timestamp}; pub use errors_v1::{ DecodeFromJsonErrorV1 as TransactionV1DecodeFromJsonError, ErrorV1 as TransactionV1Error, From 3ec76711a855c8ebb50528c4c97aec951164c2ef Mon Sep 17 00:00:00 2001 From: Karan Dhareshwar Date: Tue, 12 May 2026 15:32:38 -0500 Subject: [PATCH 11/13] Run make format --- binary_port/src/error_code.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binary_port/src/error_code.rs b/binary_port/src/error_code.rs index 983c54bc5f..9ca223476c 100644 --- a/binary_port/src/error_code.rs +++ b/binary_port/src/error_code.rs @@ -371,7 +371,7 @@ pub enum ErrorCode { #[error("the transaction invocation target is unsupported under V2 runtime")] UnsupportedInvocationTarget = 117, #[error("the transaction contained an invalid initiator")] - InvalidInitiator + InvalidInitiator, } impl TryFrom for ErrorCode { From d2734739aed6e3b660079856f6ac035e1c63a155 Mon Sep 17 00:00:00 2001 From: Joe Sacher <321623+sacherjj@users.noreply.github.com> Date: Wed, 13 May 2026 08:44:20 -0400 Subject: [PATCH 12/13] Correcting issue with cargo-deb install via fixed fork. --- .github/workflows/push-artifacts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push-artifacts.yml b/.github/workflows/push-artifacts.yml index 14a8111c49..4f01879e6e 100644 --- a/.github/workflows/push-artifacts.yml +++ b/.github/workflows/push-artifacts.yml @@ -40,7 +40,7 @@ jobs: python3 --version - name: Install cargo deb - run: cargo install cargo-deb + run: cargo install --git https://github.com/sacherjj/cargo-deb cargo-deb - name: Build update package run: ./ci/build_update_package.sh From ebbdf719bee6c34345a50a2387b9d36f70a81262 Mon Sep 17 00:00:00 2001 From: Joe Sacher <321623+sacherjj@users.noreply.github.com> Date: Tue, 26 May 2026 10:24:09 -0400 Subject: [PATCH 13/13] Production Config Files for 2.2.1 release. --- resources/integration-test/chainspec.toml | 4 ++-- resources/mainnet/chainspec.toml | 4 ++-- resources/mainnet/global_state.toml | 11 ----------- resources/testnet/chainspec.toml | 6 +++--- resources/testnet/global_state.toml | 11 ----------- 5 files changed, 7 insertions(+), 29 deletions(-) delete mode 100644 resources/mainnet/global_state.toml delete mode 100644 resources/testnet/global_state.toml diff --git a/resources/integration-test/chainspec.toml b/resources/integration-test/chainspec.toml index 0ec491a465..1621e2049b 100644 --- a/resources/integration-test/chainspec.toml +++ b/resources/integration-test/chainspec.toml @@ -1,6 +1,6 @@ [protocol] # Protocol version. -version = '2.2.2' +version = '2.2.3' # Whether we need to clear latest blocks back to the switch block just before the activation point or not. hard_reset = true # This protocol version becomes active at this point. @@ -11,7 +11,7 @@ hard_reset = true # in contract-runtime for computing genesis post-state hash. # # If it is an integer, it represents an era ID, meaning the protocol version becomes active at the start of this era. -activation_point = 19672 +activation_point = 20430 [network] # Human readable name for convenience; the genesis_hash is the true identifier. The name influences the genesis hash by diff --git a/resources/mainnet/chainspec.toml b/resources/mainnet/chainspec.toml index 3448dc9935..344195cc52 100644 --- a/resources/mainnet/chainspec.toml +++ b/resources/mainnet/chainspec.toml @@ -1,6 +1,6 @@ [protocol] # Protocol version. -version = '2.2.0' +version = '2.2.1' # Whether we need to clear latest blocks back to the switch block just before the activation point or not. hard_reset = true # This protocol version becomes active at this point. @@ -11,7 +11,7 @@ hard_reset = true # in contract-runtime for computing genesis post-state hash. # # If it is an integer, it represents an era ID, meaning the protocol version becomes active at the start of this era. -activation_point = 21742 +activation_point = 22426 [network] # Human readable name for convenience; the genesis_hash is the true identifier. The name influences the genesis hash by diff --git a/resources/mainnet/global_state.toml b/resources/mainnet/global_state.toml deleted file mode 100644 index f723398768..0000000000 --- a/resources/mainnet/global_state.toml +++ /dev/null @@ -1,11 +0,0 @@ -# The below entry will write the value into an account purse balance. -# -# Key fd37afc9c5c70f04300e55977a07db92eada2f0b3538840752afb8cade90ed3b is the main purse -# for CA Treasury 1 account 02033c97db0328743d0a3b7654751efab570caa6e6c011869f34e65560dc011a348c -# -# Value AAkAAAAIutchOy3mGUII is base64 encoding of 4763091162861000634 motes in U512 data type. -# This represents 33% of the supply at block 6972606 (14433609569450460644) -# plus 4942348218 motes - the current balance of this account. -[[entries]] -key = "balance-fd37afc9c5c70f04300e55977a07db92eada2f0b3538840752afb8cade90ed3b" -value = "AAkAAAAIutchOy3mGUII" diff --git a/resources/testnet/chainspec.toml b/resources/testnet/chainspec.toml index 2158da03cb..4aa8418029 100644 --- a/resources/testnet/chainspec.toml +++ b/resources/testnet/chainspec.toml @@ -1,6 +1,6 @@ [protocol] # Protocol version. -version = '2.2.0' +version = '2.2.1' # Whether we need to clear latest blocks back to the switch block just before the activation point or not. hard_reset = true # This protocol version becomes active at this point. @@ -11,7 +11,7 @@ hard_reset = true # in contract-runtime for computing genesis post-state hash. # # If it is an integer, it represents an era ID, meaning the protocol version becomes active at the start of this era. -activation_point = 21500 +activation_point = 22223 [network] # Human readable name for convenience; the genesis_hash is the true identifier. The name influences the genesis hash by @@ -180,7 +180,7 @@ baseline_motes_amount = 2_500_000_000 # Flag on whether ambiguous entity versions returns an execution error. trap_on_ambiguous_entity_version = false # Controls how rewards are handled by the network -# purse uref-b06a1ab0cfb52b5d4f9a08b68a5dbe78e999de0b0484c03e64f5c03897cf637b-007 belongs to +# purse uref-b06a1ab0cfb52b5d4f9a08b68a5dbe78e999de0b0484c03e64f5c03897cf637b-007 belongs to # account 018afa98ca4be12d613617f7339a2d576950a2f9a92102ca4d6508ee31b54d2c02 (faucet account for testnet) rewards_handling = { type = 'sustain', ratio = [2,8], purse_address = "uref-b06a1ab0cfb52b5d4f9a08b68a5dbe78e999de0b0484c03e64f5c03897cf637b-007" } diff --git a/resources/testnet/global_state.toml b/resources/testnet/global_state.toml deleted file mode 100644 index 9995ac32b7..0000000000 --- a/resources/testnet/global_state.toml +++ /dev/null @@ -1,11 +0,0 @@ -# The below entry will write the value into an account purse balance. -# -# Key f574ebcb676fb9fdee9f24b1d18a298616b08e64705aac773c7f8bf3bd213eb0 is the main purse -# for account 016f1236ff250d958b7f7ded4a942bd79e201120949b283f7019da970299a34dce -# -# Value AAkAAAAIAJIsyddVti4I is base64 encoding of 3332312435249620480 motes in U512 data type. -# This represents 33% of the total_supply at block 7163088 (10097916461362486077) -# plus 3 CSPR (3000000000 motes) balance of this account at upgrade. -[[entries]] -key = "balance-f574ebcb676fb9fdee9f24b1d18a298616b08e64705aac773c7f8bf3bd213eb0" -value = "AAkAAAAIAKarJ4HAPi4I"