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 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/binary_port/src/error_code.rs b/binary_port/src/error_code.rs index e3ea4b3a0a..9ca223476c 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/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/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index ee77a15fd6..a1e05d1d01 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -250,6 +250,11 @@ enum TestScenario { ContractVersionExistance, ), VmCasperV2ByPackageHash, + // For both these scenarios, + // true means use public key + // false means use account hash + FromPeerWithSystemInitiator(bool), + FromClientWithSystemInitiator(bool), } impl TestScenario { @@ -268,7 +273,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 +311,8 @@ impl TestScenario { | TestScenario::RedelegateExceedingMaximumDelegation | TestScenario::DelegateExceedingMaximumDelegation | TestScenario::VmCasperV2ByPackageHash - | TestScenario::V1ByPackage(..) => Source::Client, + | TestScenario::V1ByPackage(..) + | TestScenario::FromClientWithSystemInitiator(_) => Source::Client, } } @@ -324,6 +331,28 @@ impl TestScenario { txn.invalidate(); Transaction::from(txn) } + 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(); + 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()) + ) + }; + Transaction::from(txn) + } TestScenario::FromClientInvalidTransactionZeroPayment(TxnType::V1) => { let txn = TransactionV1Builder::new_session( false, @@ -937,6 +966,7 @@ impl TestScenario { HashOrName::Name => true, } }, + TestScenario::FromPeerWithSystemInitiator(_) | TestScenario::FromClientWithSystemInitiator(_) => false, } } @@ -1756,6 +1786,15 @@ async fn run_transaction_acceptor_without_timeout( ) ), }, + TestScenario::FromPeerWithSystemInitiator(_) + | TestScenario::FromClientWithSystemInitiator(_) => { + matches!( + event, + Event::TransactionAcceptorAnnouncement( + TransactionAcceptorAnnouncement::InvalidTransaction { .. } + ) + ) + } } }; runner @@ -3065,3 +3104,57 @@ async fn should_succeed_when_asking_for_active_exact_version() { .await; assert!(result.is_ok()) } + +#[tokio::test] +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::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::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::Parameters { + failure: ParameterFailure::InvalidAssociatedKeys { .. }, + .. + }) + )) +} + +#[tokio::test] +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::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::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::Parameters { + failure: ParameterFailure::InvalidAssociatedKeys { .. }, + .. + }) + )) +} 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/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/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" 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/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/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" 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 41d4b7ac30..f7347ef809 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -50,7 +50,7 @@ use super::{ }; #[cfg(any(feature = "std", feature = "testing", test))] use crate::bytesrepr::Bytes; -use crate::{Digest, DisplayIter, SecretKey, TimeDiff, Timestamp}; +use crate::{Digest, DisplayIter, PublicKey, SecretKey, TimeDiff, Timestamp}; pub use errors_v1::{ DecodeFromJsonErrorV1 as TransactionV1DecodeFromJsonError, ErrorV1 as TransactionV1Error, @@ -202,6 +202,43 @@ 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, + should_use_public_key: bool, + initiator_addr_and_secret_key: InitiatorAddrAndSecretKey, + ) -> TransactionV1 { + 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, + 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 +369,37 @@ 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 { + 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::PaymentLimited { + payment_amount: 10_000_000_000u64, + gas_price_tolerance: 1, + standard_payment: false, + }; + TransactionV1::build_with_system_initiator( + "casper-example".to_string(), + timestamp, + TimeDiff::from_millis(ttl_millis), + pricing_mode, + container.to_map().unwrap(), + should_use_public_key, + initiator_addr_and_secret_key, + ) + } + #[cfg(any(all(feature = "std", feature = "testing"), test))] pub fn random_with_timestamp_and_ttl( rng: &mut TestRng, @@ -443,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() { 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, } } }