diff --git a/Cargo.lock b/Cargo.lock index 6c954fc481..a8a13383c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -467,6 +467,22 @@ dependencies = [ "casper-types", ] +[[package]] +name = "casper-binary-port" +version = "1.0.0" +dependencies = [ + "bincode", + "casper-types", + "once_cell", + "rand", + "schemars", + "serde", + "serde-map-to-array", + "serde_json", + "serde_test", + "thiserror", +] + [[package]] name = "casper-contract" version = "3.0.0" @@ -481,6 +497,7 @@ dependencies = [ name = "casper-engine-test-support" version = "6.0.0" dependencies = [ + "blake2", "casper-execution-engine", "casper-storage", "casper-types", @@ -495,7 +512,7 @@ dependencies = [ "rand", "serde", "tempfile", - "toml", + "toml 0.5.11", "version-sync", ] @@ -609,6 +626,7 @@ dependencies = [ "base64 0.13.1", "bincode", "bytes", + "casper-binary-port", "casper-execution-engine", "casper-json-rpc", "casper-storage", @@ -678,7 +696,7 @@ dependencies = [ "tokio-serde", "tokio-stream", "tokio-util 0.6.10", - "toml", + "toml 0.7.8", "tower", "tracing", "tracing-futures", @@ -3017,7 +3035,7 @@ dependencies = [ "lmdb-rkv", "rand", "serde", - "toml", + "toml 0.5.11", ] [[package]] @@ -5209,6 +5227,15 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_test" version = "1.0.176" @@ -5828,6 +5855,41 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -6292,7 +6354,7 @@ dependencies = [ "regex", "semver", "syn 1.0.109", - "toml", + "toml 0.5.11", "url", ] @@ -6666,6 +6728,15 @@ version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/Cargo.toml b/Cargo.toml index 60aefc1ef0..4cd137ca41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "types", "utils/global-state-update-gen", "utils/validation", + "binary_port" ] default-members = [ @@ -25,6 +26,7 @@ default-members = [ "types", "utils/global-state-update-gen", "utils/validation", + "binary_port", ] # Include debug symbols in the release build of `casper-engine-tests` so that `simple-transfer` will yield useful diff --git a/Makefile b/Makefile index 30abce3cf5..e0e8810b70 100644 --- a/Makefile +++ b/Makefile @@ -76,8 +76,8 @@ resources/local/chainspec.toml: generate-chainspec.sh resources/local/chainspec. @./$< .PHONY: test-rs -test-rs: resources/local/chainspec.toml - $(LEGACY) $(DISABLE_LOGGING) $(CARGO) test --all-features $(CARGO_FLAGS) -- --nocapture +-k test-rs: resources/local/chainspec.toml + $(LEGACY) $(DISABLE_LOGGING) $(CARGO) test --all-features --no-fail-fast $(CARGO_FLAGS) -- --nocapture .PHONY: resources/local/chainspec.toml test-rs-no-default-features: @@ -142,7 +142,7 @@ lint-smart-contracts: .PHONY: audit-rs audit-rs: - $(CARGO) audit --ignore RUSTSEC-2024-0006 --ignore RUSTSEC-2024-0003 --ignore RUSTSEC-2024-0019 + $(CARGO) audit --ignore RUSTSEC-2024-0006 --ignore RUSTSEC-2024-0003 --ignore RUSTSEC-2024-0019 --ignore RUSTSEC-2024-0332 .PHONY: audit-as audit-as: diff --git a/binary_port/Cargo.toml b/binary_port/Cargo.toml new file mode 100644 index 0000000000..058181cae4 --- /dev/null +++ b/binary_port/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "casper-binary-port" +version = "1.0.0" +edition = "2018" +description = "Types for the casper node binary port" +documentation = "https://docs.rs/casper-binary-port" +readme = "README.md" +homepage = "https://casperlabs.io" +repository = "https://github.com/CasperLabs/casper-node/tree/master/binary_port" +license = "Apache-2.0" +exclude = ["proptest-regressions"] + +[dependencies] +casper-types = { version = "3.0.0", path = "../types", features = ["datasize", "json-schema", "std"] } +serde = { version = "1.0.183", features = ["derive"] } +thiserror = "1.0.45" +serde-map-to-array = "1.1.0" +once_cell = { version = "1.5.2", optional = true } +schemars = { version = "0.8.16", features = ["preserve_order", "impl_json_schema"] } +bincode = "1.3.3" + +[dev-dependencies] +casper-types = { path = "../types", features = ["datasize", "json-schema", "std", "testing"] } +rand = "0.8.3" +serde_json = "1" +serde_test = "1" + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] diff --git a/binary_port/README.md b/binary_port/README.md new file mode 100644 index 0000000000..80099cc02b --- /dev/null +++ b/binary_port/README.md @@ -0,0 +1,16 @@ +# `casper-binary-port` + +[![LOGO](https://raw.githubusercontent.com/casper-network/casper-node/master/images/casper-association-logo-primary.svg)](https://casper.network/) + +[![Build Status](https://drone-auto-casper-network.casperlabs.io/api/badges/casper-network/casper-node/status.svg?branch=dev)](http://drone-auto-casper-network.casperlabs.io/casper-network/casper-node) +[![Crates.io](https://img.shields.io/crates/v/casper-hashing)](https://crates.io/crates/casper-binary-port) +[![Documentation](https://docs.rs/casper-hashing/badge.svg)](https://docs.rs/casper-binary-port) +[![License](https://img.shields.io/badge/license-Apache-blue)](https://github.com/CasperLabs/casper-node/blob/master/LICENSE) + +Types for the binary port on a casper network node. + +[Node Operator Guide](https://docs.casperlabs.io/operators/) + +## License + +Licensed under the [Apache License Version 2.0](https://github.com/casper-network/casper-node/blob/master/LICENSE). diff --git a/types/src/binary_port/binary_request.rs b/binary_port/src/binary_request.rs similarity index 69% rename from types/src/binary_port/binary_request.rs rename to binary_port/src/binary_request.rs index b1c7ecefe5..0441c53e6a 100644 --- a/types/src/binary_port/binary_request.rs +++ b/binary_port/src/binary_request.rs @@ -1,18 +1,16 @@ use core::convert::TryFrom; -use crate::{ +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, - BlockHeader, Digest, ProtocolVersion, Timestamp, Transaction, + ProtocolVersion, Transaction, }; -use alloc::vec::Vec; -use super::get_request::GetRequest; +use crate::get_request::GetRequest; #[cfg(test)] -use rand::Rng; - +use casper_types::testing::TestRng; #[cfg(test)] -use crate::{testing::TestRng, Block, TestBlockV1Builder}; +use rand::Rng; /// The header of a binary request. #[derive(Debug, PartialEq)] @@ -92,16 +90,8 @@ pub enum BinaryRequest { }, /// Request to execute a transaction speculatively. TrySpeculativeExec { - /// State root on top of which to execute deploy. - state_root_hash: Digest, - /// Block time. - block_time: Timestamp, - /// Protocol version used when creating the original block. - protocol_version: ProtocolVersion, /// Transaction to execute. transaction: Transaction, - /// Block header of block at which we should perform speculative execution. - speculative_exec_at_block: BlockHeader, }, } @@ -122,18 +112,9 @@ impl BinaryRequest { BinaryRequestTag::TryAcceptTransaction => Self::TryAcceptTransaction { transaction: Transaction::random(rng), }, - BinaryRequestTag::TrySpeculativeExec => { - let block_v1 = TestBlockV1Builder::new().build(rng); - let block = Block::V1(block_v1); - - Self::TrySpeculativeExec { - state_root_hash: Digest::random(rng), - block_time: Timestamp::random(rng), - protocol_version: ProtocolVersion::from_parts(rng.gen(), rng.gen(), rng.gen()), - transaction: Transaction::random(rng), - speculative_exec_at_block: block.take_header(), - } - } + BinaryRequestTag::TrySpeculativeExec => Self::TrySpeculativeExec { + transaction: Transaction::random(rng), + }, } } } @@ -149,19 +130,7 @@ impl ToBytes for BinaryRequest { match self { BinaryRequest::Get(inner) => inner.write_bytes(writer), BinaryRequest::TryAcceptTransaction { transaction } => transaction.write_bytes(writer), - BinaryRequest::TrySpeculativeExec { - transaction, - state_root_hash, - block_time, - protocol_version, - speculative_exec_at_block, - } => { - transaction.write_bytes(writer)?; - state_root_hash.write_bytes(writer)?; - block_time.write_bytes(writer)?; - protocol_version.write_bytes(writer)?; - speculative_exec_at_block.write_bytes(writer) - } + BinaryRequest::TrySpeculativeExec { transaction } => transaction.write_bytes(writer), } } @@ -169,19 +138,7 @@ impl ToBytes for BinaryRequest { match self { BinaryRequest::Get(inner) => inner.serialized_length(), BinaryRequest::TryAcceptTransaction { transaction } => transaction.serialized_length(), - BinaryRequest::TrySpeculativeExec { - transaction, - state_root_hash, - block_time, - protocol_version, - speculative_exec_at_block, - } => { - transaction.serialized_length() - + state_root_hash.serialized_length() - + block_time.serialized_length() - + protocol_version.serialized_length() - + speculative_exec_at_block.serialized_length() - } + BinaryRequest::TrySpeculativeExec { transaction } => transaction.serialized_length(), } } } @@ -204,20 +161,7 @@ impl TryFrom<(BinaryRequestTag, &[u8])> for BinaryRequest { } BinaryRequestTag::TrySpeculativeExec => { let (transaction, remainder) = FromBytes::from_bytes(bytes)?; - let (state_root_hash, remainder) = FromBytes::from_bytes(remainder)?; - let (block_time, remainder) = FromBytes::from_bytes(remainder)?; - let (protocol_version, remainder) = FromBytes::from_bytes(remainder)?; - let (speculative_exec_at_block, remainder) = FromBytes::from_bytes(remainder)?; - ( - BinaryRequest::TrySpeculativeExec { - transaction, - state_root_hash, - block_time, - protocol_version, - speculative_exec_at_block, - }, - remainder, - ) + (BinaryRequest::TrySpeculativeExec { transaction }, remainder) } }; if !remainder.is_empty() { @@ -277,7 +221,7 @@ pub struct InvalidBinaryRequestTag(u8); #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn header_bytesrepr_roundtrip() { diff --git a/types/src/binary_port/binary_response.rs b/binary_port/src/binary_response.rs similarity index 82% rename from types/src/binary_port/binary_response.rs rename to binary_port/src/binary_response.rs index f821bc3b7a..6d1fddb51d 100644 --- a/types/src/binary_port/binary_response.rs +++ b/binary_port/src/binary_response.rs @@ -1,19 +1,17 @@ -use crate::{ +use casper_types::{ bytesrepr::{self, Bytes, FromBytes, ToBytes}, ProtocolVersion, }; -use alloc::vec::Vec; - -#[cfg(test)] -use crate::testing::TestRng; -use super::{ +use crate::{ binary_response_header::BinaryResponseHeader, + error_code::ErrorCode, payload_type::{PayloadEntity, PayloadType}, - record_id::RecordId, - DbRawBytesSpec, ErrorCode, }; +#[cfg(test)] +use casper_types::testing::TestRng; + /// The response used in the binary port protocol. #[derive(Debug, PartialEq)] pub struct BinaryResponse { @@ -40,27 +38,15 @@ impl BinaryResponse { } } - /// Creates new binary response from raw DB bytes. - pub fn from_db_raw_bytes( - record_id: RecordId, - spec: Option, + /// Creates new binary response from raw bytes. + pub fn from_raw_bytes( + payload_type: PayloadType, + payload: Vec, protocol_version: ProtocolVersion, ) -> Self { - match spec { - Some(DbRawBytesSpec { - is_legacy, - raw_bytes, - }) => BinaryResponse { - header: BinaryResponseHeader::new( - Some(PayloadType::new_from_record_id(record_id, is_legacy)), - protocol_version, - ), - payload: raw_bytes, - }, - None => BinaryResponse { - header: BinaryResponseHeader::new_error(ErrorCode::NotFound, protocol_version), - payload: vec![], - }, + BinaryResponse { + header: BinaryResponseHeader::new(Some(payload_type), protocol_version), + payload, } } @@ -165,7 +151,7 @@ impl FromBytes for BinaryResponse { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/binary_response_and_request.rs b/binary_port/src/binary_response_and_request.rs similarity index 79% rename from types/src/binary_port/binary_response_and_request.rs rename to binary_port/src/binary_response_and_request.rs index 78d4785d41..a6a25c36f0 100644 --- a/types/src/binary_port/binary_response_and_request.rs +++ b/binary_port/src/binary_response_and_request.rs @@ -1,17 +1,13 @@ -use crate::bytesrepr::{self, Bytes, FromBytes, ToBytes}; +use casper_types::{ + bytesrepr::{self, Bytes, FromBytes, ToBytes}, + ProtocolVersion, +}; -use super::binary_response::BinaryResponse; -#[cfg(any(feature = "testing", test))] -use super::payload_type::PayloadEntity; -use alloc::vec::Vec; - -#[cfg(any(feature = "testing", test))] -use super::record_id::RecordId; -#[cfg(any(feature = "testing", test))] -use crate::ProtocolVersion; +use crate::{binary_response::BinaryResponse, payload_type::PayloadEntity, PayloadType}; +use crate::record_id::RecordId; #[cfg(test)] -use crate::testing::TestRng; +use casper_types::testing::TestRng; /// The binary response along with the original binary request attached. #[derive(Debug, PartialEq)] @@ -31,37 +27,29 @@ impl BinaryResponseAndRequest { } } - /// Returns a new binary response with specified data and no original request. - #[cfg(any(feature = "testing", test))] + /// Returns a new binary response with specified data and no original request. pub fn new_test_response( record_id: RecordId, data: &A, protocol_version: ProtocolVersion, ) -> BinaryResponseAndRequest { - use super::DbRawBytesSpec; - - let response = BinaryResponse::from_db_raw_bytes( - record_id, - Some(DbRawBytesSpec::new_current(&data.to_bytes().unwrap())), + let response = BinaryResponse::from_raw_bytes( + PayloadType::from_record_id(record_id, false), + data.to_bytes().unwrap(), protocol_version, ); Self::new(response, &[]) } /// Returns a new binary response with specified legacy data and no original request. - #[cfg(any(feature = "testing", test))] pub fn new_legacy_test_response( record_id: RecordId, data: &A, protocol_version: ProtocolVersion, ) -> BinaryResponseAndRequest { - use super::DbRawBytesSpec; - - let response = BinaryResponse::from_db_raw_bytes( - record_id, - Some(DbRawBytesSpec::new_legacy( - &bincode::serialize(data).unwrap(), - )), + let response = BinaryResponse::from_raw_bytes( + PayloadType::from_record_id(record_id, true), + bincode::serialize(data).unwrap(), protocol_version, ); Self::new(response, &[]) @@ -143,7 +131,7 @@ impl From for BinaryResponse { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/binary_response_header.rs b/binary_port/src/binary_response_header.rs similarity index 95% rename from types/src/binary_port/binary_response_header.rs rename to binary_port/src/binary_response_header.rs index 025a9068e6..fb25deea25 100644 --- a/types/src/binary_port/binary_response_header.rs +++ b/binary_port/src/binary_response_header.rs @@ -1,15 +1,14 @@ -#[cfg(test)] -use crate::testing::TestRng; -use crate::{ +use crate::{error_code::ErrorCode, payload_type::PayloadType}; +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, ProtocolVersion, }; -use alloc::vec::Vec; + +#[cfg(test)] +use casper_types::testing::TestRng; #[cfg(test)] use rand::Rng; -use super::{ErrorCode, PayloadType}; - /// Header of the binary response. #[derive(Debug, PartialEq)] pub struct BinaryResponseHeader { @@ -122,7 +121,7 @@ impl FromBytes for BinaryResponseHeader { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/dictionary_item_identifier.rs b/binary_port/src/dictionary_item_identifier.rs similarity index 98% rename from types/src/binary_port/dictionary_item_identifier.rs rename to binary_port/src/dictionary_item_identifier.rs index 241c50e40a..44277b8ddb 100644 --- a/types/src/binary_port/dictionary_item_identifier.rs +++ b/binary_port/src/dictionary_item_identifier.rs @@ -1,11 +1,9 @@ -use alloc::{string::String, vec::Vec}; - +#[cfg(test)] +use casper_types::testing::TestRng; #[cfg(test)] use rand::Rng; -#[cfg(test)] -use crate::testing::TestRng; -use crate::{ +use casper_types::{ account::AccountHash, bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, DictionaryAddr, EntityAddr, HashAddr, URef, @@ -241,7 +239,7 @@ impl FromBytes for DictionaryItemIdentifier { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/error_code.rs b/binary_port/src/error_code.rs similarity index 64% rename from types/src/binary_port/error_code.rs rename to binary_port/src/error_code.rs index fe0bca1f5e..0460806adb 100644 --- a/types/src/binary_port/error_code.rs +++ b/binary_port/src/error_code.rs @@ -1,49 +1,53 @@ use core::{convert::TryFrom, fmt}; +use casper_types::InvalidTransaction; + /// The error code indicating the result of handling the binary request. -#[derive(Debug, Clone)] -#[cfg_attr(feature = "std", derive(thiserror::Error))] +#[derive(Debug, Clone, thiserror::Error)] #[repr(u8)] pub enum ErrorCode { /// Request executed correctly. - #[cfg_attr(feature = "std", error("request executed correctly"))] + #[error("request executed correctly")] NoError = 0, /// This function is disabled. - #[cfg_attr(feature = "std", error("this function is disabled"))] + #[error("this function is disabled")] FunctionDisabled = 1, /// Data not found. - #[cfg_attr(feature = "std", error("data not found"))] + #[error("data not found")] NotFound = 2, /// Root not found. - #[cfg_attr(feature = "std", error("root not found"))] + #[error("root not found")] RootNotFound = 3, /// Invalid deploy item variant. - #[cfg_attr(feature = "std", error("invalid deploy item variant"))] - InvalidDeployItemVariant = 4, + #[error("invalid deploy item variant")] + InvalidItemVariant = 4, /// Wasm preprocessing. - #[cfg_attr(feature = "std", error("wasm preprocessing"))] + #[error("wasm preprocessing")] WasmPreprocessing = 5, /// Invalid protocol version. - #[cfg_attr(feature = "std", error("unsupported protocol version"))] + #[error("unsupported protocol version")] UnsupportedProtocolVersion = 6, /// Invalid transaction. - #[cfg_attr(feature = "std", error("invalid transaction"))] + #[error("invalid transaction")] InvalidTransaction = 7, /// Internal error. - #[cfg_attr(feature = "std", error("internal error"))] + #[error("internal error")] InternalError = 8, /// The query to global state failed. - #[cfg_attr(feature = "std", error("the query to global state failed"))] - QueryFailedToExecute = 9, + #[error("the query to global state failed")] + FailedQuery = 9, /// Bad request. - #[cfg_attr(feature = "std", error("bad request"))] + #[error("bad request")] BadRequest = 10, /// Received an unsupported type of request. - #[cfg_attr(feature = "std", error("unsupported request"))] + #[error("unsupported request")] UnsupportedRequest = 11, /// Dictionary URef not found. - #[cfg_attr(feature = "std", error("dictionary URef not found"))] + #[error("dictionary URef not found")] DictionaryURefNotFound = 12, + /// This node has no complete blocks. + #[error("no complete blocks")] + NoCompleteBlocks = 13, } impl TryFrom for ErrorCode { @@ -55,15 +59,16 @@ impl TryFrom for ErrorCode { 1 => Ok(ErrorCode::FunctionDisabled), 2 => Ok(ErrorCode::NotFound), 3 => Ok(ErrorCode::RootNotFound), - 4 => Ok(ErrorCode::InvalidDeployItemVariant), + 4 => Ok(ErrorCode::InvalidItemVariant), 5 => Ok(ErrorCode::WasmPreprocessing), 6 => Ok(ErrorCode::UnsupportedProtocolVersion), 7 => Ok(ErrorCode::InvalidTransaction), 8 => Ok(ErrorCode::InternalError), - 9 => Ok(ErrorCode::QueryFailedToExecute), + 9 => Ok(ErrorCode::FailedQuery), 10 => Ok(ErrorCode::BadRequest), 11 => Ok(ErrorCode::UnsupportedRequest), 12 => Ok(ErrorCode::DictionaryURefNotFound), + 13 => Ok(ErrorCode::NoCompleteBlocks), _ => Err(UnknownErrorCode), } } @@ -79,5 +84,10 @@ impl fmt::Display for UnknownErrorCode { } } -#[cfg(feature = "std")] impl std::error::Error for UnknownErrorCode {} + +impl From for ErrorCode { + fn from(_value: InvalidTransaction) -> Self { + ErrorCode::InvalidTransaction + } +} diff --git a/types/src/binary_port/get_request.rs b/binary_port/src/get_request.rs similarity index 95% rename from types/src/binary_port/get_request.rs rename to binary_port/src/get_request.rs index 01fb8f23b7..e11af5ff09 100644 --- a/types/src/binary_port/get_request.rs +++ b/binary_port/src/get_request.rs @@ -1,13 +1,11 @@ -use crate::bytesrepr::{self, Bytes, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}; -use alloc::vec::Vec; +use casper_types::bytesrepr::{self, Bytes, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}; -#[cfg(test)] -use rand::Rng; +use crate::state_request::GlobalStateRequest; #[cfg(test)] -use crate::testing::TestRng; - -use super::state_request::GlobalStateRequest; +use casper_types::testing::TestRng; +#[cfg(test)] +use rand::Rng; const RECORD_TAG: u8 = 0; const INFORMATION_TAG: u8 = 1; @@ -134,7 +132,7 @@ impl FromBytes for GetRequest { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/global_state_query_result.rs b/binary_port/src/global_state_query_result.rs similarity index 93% rename from types/src/binary_port/global_state_query_result.rs rename to binary_port/src/global_state_query_result.rs index b414c388cd..6dfab35e76 100644 --- a/types/src/binary_port/global_state_query_result.rs +++ b/binary_port/src/global_state_query_result.rs @@ -1,17 +1,16 @@ //! The result of the query for the global state value. -use crate::{ +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, global_state::TrieMerkleProof, Key, StoredValue, }; -use alloc::vec::Vec; #[cfg(test)] -use crate::testing::TestRng; +use casper_types::testing::TestRng; #[cfg(test)] -use crate::{ByteCode, ByteCodeKind}; +use casper_types::{ByteCode, ByteCodeKind}; /// Carries the successful result of the global state query. #[derive(Debug, PartialEq, Clone)] @@ -43,7 +42,7 @@ impl GlobalStateQueryResult { #[cfg(test)] pub(crate) fn random_invalid(rng: &mut TestRng) -> Self { - use crate::{global_state::TrieMerkleProofStep, CLValue}; + use casper_types::{global_state::TrieMerkleProofStep, CLValue}; use rand::Rng; // Note: This does NOT create a logically-valid struct. Instance created by this function // should be used in `bytesrepr` tests only. @@ -107,7 +106,7 @@ impl FromBytes for GlobalStateQueryResult { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/information_request.rs b/binary_port/src/information_request.rs similarity index 99% rename from types/src/binary_port/information_request.rs rename to binary_port/src/information_request.rs index 215377a68f..42873f0f47 100644 --- a/types/src/binary_port/information_request.rs +++ b/binary_port/src/information_request.rs @@ -1,18 +1,16 @@ -use alloc::vec::Vec; use core::convert::TryFrom; #[cfg(test)] use rand::Rng; +use crate::get_request::GetRequest; #[cfg(test)] -use crate::testing::TestRng; -use crate::{ +use casper_types::testing::TestRng; +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, BlockIdentifier, TransactionHash, }; -use super::GetRequest; - /// Request for information from the node. #[derive(Clone, Debug, PartialEq)] pub enum InformationRequest { @@ -365,7 +363,7 @@ pub struct UnknownInformationRequestTag(u16); #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn tag_roundtrip() { diff --git a/types/src/binary_port.rs b/binary_port/src/lib.rs similarity index 51% rename from types/src/binary_port.rs rename to binary_port/src/lib.rs index 0d809fb905..00ac6a903f 100644 --- a/types/src/binary_port.rs +++ b/binary_port/src/lib.rs @@ -1,4 +1,5 @@ -//! The binary port. +//! A Rust library for types used by the binary port of a casper node. + mod binary_request; mod binary_response; mod binary_response_and_request; @@ -9,10 +10,10 @@ mod get_request; mod global_state_query_result; mod information_request; mod minimal_block_info; -#[cfg(any(feature = "std", test))] mod node_status; mod payload_type; -mod record_id; +pub mod record_id; +mod speculative_execution_result; mod state_request; mod type_wrappers; @@ -25,43 +26,13 @@ pub use error_code::ErrorCode; pub use get_request::GetRequest; pub use global_state_query_result::GlobalStateQueryResult; pub use information_request::{InformationRequest, InformationRequestTag}; -#[cfg(any(feature = "std", test))] pub use minimal_block_info::MinimalBlockInfo; -#[cfg(any(feature = "std", test))] pub use node_status::NodeStatus; pub use payload_type::{PayloadEntity, PayloadType}; -pub use record_id::RecordId; +pub use record_id::{RecordId, UnknownRecordId}; +pub use speculative_execution_result::SpeculativeExecutionResult; pub use state_request::GlobalStateRequest; pub use type_wrappers::{ ConsensusStatus, ConsensusValidatorChanges, DictionaryQueryResult, GetTrieFullResult, - LastProgress, NetworkName, ReactorStateName, SpeculativeExecutionResult, - TransactionWithExecutionInfo, Uptime, + LastProgress, NetworkName, ReactorStateName, TransactionWithExecutionInfo, Uptime, }; - -use alloc::vec::Vec; - -/// Stores raw bytes from the DB along with the flag indicating whether data come from legacy or -/// current version of the DB. -#[derive(Debug)] -pub struct DbRawBytesSpec { - is_legacy: bool, - raw_bytes: Vec, -} - -impl DbRawBytesSpec { - /// Creates a variant indicating that raw bytes are coming from the legacy database. - pub fn new_legacy(raw_bytes: &[u8]) -> Self { - Self { - is_legacy: true, - raw_bytes: raw_bytes.to_vec(), - } - } - - /// Creates a variant indicating that raw bytes are coming from the current database. - pub fn new_current(raw_bytes: &[u8]) -> Self { - Self { - is_legacy: false, - raw_bytes: raw_bytes.to_vec(), - } - } -} diff --git a/types/src/binary_port/minimal_block_info.rs b/binary_port/src/minimal_block_info.rs similarity index 89% rename from types/src/binary_port/minimal_block_info.rs rename to binary_port/src/minimal_block_info.rs index 7e4708951c..21552d0795 100644 --- a/types/src/binary_port/minimal_block_info.rs +++ b/binary_port/src/minimal_block_info.rs @@ -1,24 +1,19 @@ -use crate::{ +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, Block, BlockHash, Digest, EraId, PublicKey, Timestamp, }; -use alloc::vec::Vec; -#[cfg(feature = "json-schema")] -use schemars::JsonSchema; -#[cfg(any(feature = "std", test))] use serde::{Deserialize, Serialize}; #[cfg(test)] use rand::Rng; +use schemars::JsonSchema; #[cfg(test)] -use crate::testing::TestRng; +use casper_types::testing::TestRng; /// Minimal info about a `Block` needed to satisfy the node status request. -#[derive(Debug, PartialEq, Eq)] -#[cfg_attr(any(feature = "std", test), derive(Serialize, Deserialize))] -#[cfg_attr(feature = "json-schema", derive(JsonSchema))] -#[cfg_attr(any(feature = "std", test), serde(deny_unknown_fields))] +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] pub struct MinimalBlockInfo { hash: BlockHash, timestamp: Timestamp, @@ -111,7 +106,7 @@ impl From for MinimalBlockInfo { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/node_status.rs b/binary_port/src/node_status.rs similarity index 97% rename from types/src/binary_port/node_status.rs rename to binary_port/src/node_status.rs index 7be4f47cb9..f0d8a8c36f 100644 --- a/types/src/binary_port/node_status.rs +++ b/binary_port/src/node_status.rs @@ -1,17 +1,15 @@ -use crate::{ +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, AvailableBlockRange, BlockHash, BlockSynchronizerStatus, Digest, NextUpgrade, Peers, PublicKey, TimeDiff, Timestamp, }; -use alloc::{string::String, vec::Vec}; #[cfg(test)] -use rand::Rng; - +use casper_types::testing::TestRng; #[cfg(test)] -use crate::testing::TestRng; +use rand::Rng; -use super::{type_wrappers::ReactorStateName, MinimalBlockInfo}; +use crate::{minimal_block_info::MinimalBlockInfo, type_wrappers::ReactorStateName}; /// Status information about the node. #[derive(Debug, PartialEq)] @@ -169,7 +167,7 @@ impl ToBytes for NodeStatus { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/payload_type.rs b/binary_port/src/payload_type.rs similarity index 96% rename from types/src/binary_port/payload_type.rs rename to binary_port/src/payload_type.rs index 21746d5a69..a68de02611 100644 --- a/types/src/binary_port/payload_type.rs +++ b/binary_port/src/payload_type.rs @@ -1,37 +1,31 @@ //! The payload type. -#[cfg(feature = "json-schema")] -use schemars::JsonSchema; +use core::{convert::TryFrom, fmt}; #[cfg(test)] use rand::Rng; - -use alloc::vec::Vec; -use core::{convert::TryFrom, fmt}; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; #[cfg(test)] -use crate::testing::TestRng; - -#[cfg(any(feature = "std", test))] -use super::NodeStatus; -use crate::{ +use casper_types::testing::TestRng; +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, execution::{ExecutionResult, ExecutionResultV1}, AvailableBlockRange, BlockBody, BlockBodyV1, BlockHeader, BlockHeaderV1, BlockSignatures, - BlockSignaturesV1, BlockSynchronizerStatus, Deploy, Peers, SignedBlock, StoredValue, - Transaction, Transfer, + BlockSignaturesV1, BlockSynchronizerStatus, ChainspecRawBytes, Deploy, NextUpgrade, Peers, + SignedBlock, StoredValue, Transaction, Transfer, }; -#[cfg(any(feature = "std", test))] -use crate::{ChainspecRawBytes, NextUpgrade}; -use super::{ +use crate::{ global_state_query_result::GlobalStateQueryResult, - record_id::RecordId, + node_status::NodeStatus, + speculative_execution_result::SpeculativeExecutionResult, type_wrappers::{ ConsensusStatus, ConsensusValidatorChanges, GetTrieFullResult, LastProgress, NetworkName, - ReactorStateName, SpeculativeExecutionResult, + ReactorStateName, }, - DictionaryQueryResult, TransactionWithExecutionInfo, Uptime, + DictionaryQueryResult, RecordId, TransactionWithExecutionInfo, Uptime, }; /// A type of the payload being returned in a binary response. @@ -63,6 +57,8 @@ pub enum PayloadType { ExecutionResultV1, /// Execution result. ExecutionResult, + /// Wasm V1 execution result. + WasmV1Result, /// Transfers. Transfers, /// Finalized deploy approvals. @@ -112,7 +108,7 @@ pub enum PayloadType { } impl PayloadType { - pub(crate) fn new_from_record_id(record_id: RecordId, is_legacy: bool) -> Self { + pub fn from_record_id(record_id: RecordId, is_legacy: bool) -> Self { match (is_legacy, record_id) { (true, RecordId::BlockHeader) => Self::BlockHeaderV1, (true, RecordId::BlockBody) => Self::BlockBodyV1, @@ -247,6 +243,7 @@ impl fmt::Display for PayloadType { PayloadType::StoredValues => write!(f, "StoredValues"), PayloadType::GetTrieFullResult => write!(f, "GetTrieFullResult"), PayloadType::NodeStatus => write!(f, "NodeStatus"), + PayloadType::WasmV1Result => write!(f, "WasmV1Result"), PayloadType::DictionaryQueryResult => write!(f, "DictionaryQueryResult"), } } @@ -287,6 +284,7 @@ const STORED_VALUES_TAG: u8 = 31; const GET_TRIE_FULL_RESULT_TAG: u8 = 32; const NODE_STATUS_TAG: u8 = 33; const DICTIONARY_QUERY_RESULT_TAG: u8 = 34; +const WASM_V1_RESULT_TAG: u8 = 35; impl ToBytes for PayloadType { fn to_bytes(&self) -> Result, bytesrepr::Error> { @@ -295,6 +293,10 @@ impl ToBytes for PayloadType { Ok(buffer) } + fn serialized_length(&self) -> usize { + U8_SERIALIZED_LENGTH + } + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { match self { PayloadType::BlockHeaderV1 => BLOCK_HEADER_V1_TAG, @@ -331,14 +333,11 @@ impl ToBytes for PayloadType { PayloadType::StoredValues => STORED_VALUES_TAG, PayloadType::GetTrieFullResult => GET_TRIE_FULL_RESULT_TAG, PayloadType::NodeStatus => NODE_STATUS_TAG, + PayloadType::WasmV1Result => WASM_V1_RESULT_TAG, PayloadType::DictionaryQueryResult => DICTIONARY_QUERY_RESULT_TAG, } .write_bytes(writer) } - - fn serialized_length(&self) -> usize { - U8_SERIALIZED_LENGTH - } } impl FromBytes for PayloadType { @@ -452,7 +451,6 @@ impl PayloadEntity for AvailableBlockRange { const PAYLOAD_TYPE: PayloadType = PayloadType::AvailableBlockRange; } -#[cfg(any(feature = "std", test))] impl PayloadEntity for ChainspecRawBytes { const PAYLOAD_TYPE: PayloadType = PayloadType::ChainspecRawBytes; } @@ -481,12 +479,10 @@ impl PayloadEntity for SpeculativeExecutionResult { const PAYLOAD_TYPE: PayloadType = PayloadType::SpeculativeExecutionResult; } -#[cfg(any(feature = "std", test))] impl PayloadEntity for NodeStatus { const PAYLOAD_TYPE: PayloadType = PayloadType::NodeStatus; } -#[cfg(any(feature = "std", test))] impl PayloadEntity for NextUpgrade { const PAYLOAD_TYPE: PayloadType = PayloadType::NextUpgrade; } @@ -518,7 +514,7 @@ impl PayloadEntity for ConsensusStatus { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/record_id.rs b/binary_port/src/record_id.rs similarity index 96% rename from types/src/binary_port/record_id.rs rename to binary_port/src/record_id.rs index f7ef6dfe36..649a574fea 100644 --- a/types/src/binary_port/record_id.rs +++ b/binary_port/src/record_id.rs @@ -5,7 +5,7 @@ use rand::Rng; use serde::Serialize; #[cfg(test)] -use crate::testing::TestRng; +use casper_types::testing::TestRng; /// An identifier of a record type. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] @@ -31,7 +31,7 @@ pub enum RecordId { impl RecordId { #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + pub fn random(rng: &mut TestRng) -> Self { match rng.gen_range(0..8) { 0 => RecordId::BlockHeader, 1 => RecordId::BlockBody, @@ -92,7 +92,7 @@ pub struct UnknownRecordId(u16); #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn tag_roundtrip() { diff --git a/binary_port/src/speculative_execution_result.rs b/binary_port/src/speculative_execution_result.rs new file mode 100644 index 0000000000..c665d78358 --- /dev/null +++ b/binary_port/src/speculative_execution_result.rs @@ -0,0 +1,118 @@ +use casper_types::{ + bytesrepr::{self, FromBytes, ToBytes}, + contract_messages::Messages, + execution::Effects, + Gas, InvalidTransaction, Transfer, +}; + +#[derive(Debug)] +pub struct SpeculativeExecutionResult { + /// List of transfers that happened during execution. + transfers: Vec, + /// Gas limit. + limit: Gas, + /// Gas consumed. + consumed: Gas, + /// Execution effects. + effects: Effects, + /// Messages emitted during execution. + messages: Messages, + /// Did the wasm execute successfully? + error: Option, +} + +impl SpeculativeExecutionResult { + pub fn new( + transfers: Vec, + limit: Gas, + consumed: Gas, + effects: Effects, + messages: Messages, + error: Option, + ) -> Self { + SpeculativeExecutionResult { + transfers, + limit, + consumed, + effects, + messages, + error, + } + } +} + +impl From for SpeculativeExecutionResult { + fn from(invalid_transaction: InvalidTransaction) -> Self { + SpeculativeExecutionResult { + transfers: Default::default(), + limit: Default::default(), + consumed: Default::default(), + effects: Default::default(), + messages: Default::default(), + error: Some(format!("{}", invalid_transaction)), + } + } +} + +impl ToBytes for SpeculativeExecutionResult { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buffer = bytesrepr::allocate_buffer(self)?; + self.write_bytes(&mut buffer)?; + Ok(buffer) + } + + fn serialized_length(&self) -> usize { + ToBytes::serialized_length(&self.transfers) + + ToBytes::serialized_length(&self.limit) + + ToBytes::serialized_length(&self.consumed) + + ToBytes::serialized_length(&self.effects) + + ToBytes::serialized_length(&self.messages) + + ToBytes::serialized_length(&self.error) + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.transfers.write_bytes(writer)?; + self.limit.write_bytes(writer)?; + self.consumed.write_bytes(writer)?; + self.effects.write_bytes(writer)?; + self.messages.write_bytes(writer)?; + self.error.write_bytes(writer) + } +} + +impl FromBytes for SpeculativeExecutionResult { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (transfers, bytes) = Vec::::from_bytes(bytes)?; + let (limit, bytes) = Gas::from_bytes(bytes)?; + let (consumed, bytes) = Gas::from_bytes(bytes)?; + let (effects, bytes) = Effects::from_bytes(bytes)?; + let (messages, bytes) = Messages::from_bytes(bytes)?; + let (error, bytes) = Option::::from_bytes(bytes)?; + Ok(( + SpeculativeExecutionResult { + transfers, + limit, + consumed, + effects, + messages, + error, + }, + bytes, + )) + } +} +// +// #[cfg(test)] +// mod tests { +// // use super::*; +// // use casper_types::testing::TestRng; +// +// #[test] +// fn bytesrepr_roundtrip() { +// todo!(); +// let rng = &mut TestRng::new(); +// +// let val = SpeculativeExecutionResult::random(rng); +// bytesrepr::test_serialization_roundtrip(&val); +// } +// } diff --git a/types/src/binary_port/state_request.rs b/binary_port/src/state_request.rs similarity index 98% rename from types/src/binary_port/state_request.rs rename to binary_port/src/state_request.rs index 830f8611c7..b7981c9ada 100644 --- a/types/src/binary_port/state_request.rs +++ b/binary_port/src/state_request.rs @@ -1,16 +1,15 @@ -use alloc::{string::String, vec::Vec}; - +#[cfg(test)] +use casper_types::testing::TestRng; #[cfg(test)] use rand::Rng; -use super::dictionary_item_identifier::DictionaryItemIdentifier; -#[cfg(test)] -use crate::testing::TestRng; -use crate::{ +use casper_types::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, Digest, GlobalStateIdentifier, Key, KeyTag, }; +use super::dictionary_item_identifier::DictionaryItemIdentifier; + const ITEM_TAG: u8 = 0; const ALL_ITEMS_TAG: u8 = 1; const TRIE_TAG: u8 = 2; @@ -52,7 +51,7 @@ pub enum GlobalStateRequest { impl GlobalStateRequest { #[cfg(test)] pub(crate) fn random(rng: &mut TestRng) -> Self { - match rng.gen_range(0..4) { + match TestRng::gen_range(rng, 0..4) { 0 => { let path_count = rng.gen_range(10..20); let state_identifier = if rng.gen() { @@ -216,7 +215,7 @@ impl FromBytes for GlobalStateRequest { #[cfg(test)] mod tests { use super::*; - use crate::testing::TestRng; + use casper_types::testing::TestRng; #[test] fn bytesrepr_roundtrip() { diff --git a/types/src/binary_port/type_wrappers.rs b/binary_port/src/type_wrappers.rs similarity index 90% rename from types/src/binary_port/type_wrappers.rs rename to binary_port/src/type_wrappers.rs index ff9f10afaa..b9d1fc4e2d 100644 --- a/types/src/binary_port/type_wrappers.rs +++ b/binary_port/src/type_wrappers.rs @@ -1,17 +1,11 @@ use core::{convert::TryFrom, num::TryFromIntError, time::Duration}; +use std::collections::BTreeMap; -use alloc::{ - collections::BTreeMap, - string::{String, ToString}, - vec::Vec, -}; #[cfg(feature = "datasize")] use datasize::DataSize; -use crate::{ +use casper_types::{ bytesrepr::{self, Bytes, FromBytes, ToBytes}, - contract_messages::Messages, - execution::ExecutionResultV2, EraId, ExecutionInfo, Key, PublicKey, TimeDiff, Timestamp, Transaction, ValidatorChange, }; @@ -163,22 +157,6 @@ impl From for Timestamp { } } -/// Type representing results of the speculative execution. -#[derive(Debug, PartialEq, Eq)] -pub struct SpeculativeExecutionResult(Option<(ExecutionResultV2, Messages)>); - -impl SpeculativeExecutionResult { - /// Constructs new speculative execution result. - pub fn new(value: Option<(ExecutionResultV2, Messages)>) -> Self { - Self(value) - } - - /// Returns the inner value. - pub fn into_inner(self) -> Option<(ExecutionResultV2, Messages)> { - self.0 - } -} - /// Type representing results of the get full trie request. #[derive(Debug, PartialEq, Eq)] pub struct GetTrieFullResult(Option); @@ -279,14 +257,14 @@ impl ToBytes for TransactionWithExecutionInfo { Ok(buffer) } + fn serialized_length(&self) -> usize { + self.transaction.serialized_length() + self.execution_info.serialized_length() + } + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { self.transaction.write_bytes(writer)?; self.execution_info.write_bytes(writer) } - - fn serialized_length(&self) -> usize { - self.transaction.serialized_length() + self.execution_info.serialized_length() - } } impl FromBytes for TransactionWithExecutionInfo { @@ -350,7 +328,6 @@ impl_bytesrepr_for_type_wrapper!(ConsensusValidatorChanges); impl_bytesrepr_for_type_wrapper!(NetworkName); impl_bytesrepr_for_type_wrapper!(ReactorStateName); impl_bytesrepr_for_type_wrapper!(LastProgress); -impl_bytesrepr_for_type_wrapper!(SpeculativeExecutionResult); impl_bytesrepr_for_type_wrapper!(GetTrieFullResult); #[cfg(test)] @@ -359,7 +336,9 @@ mod tests { use rand::Rng; use super::*; - use crate::{execution::ExecutionResult, testing::TestRng, BlockHash, CLValue, StoredValue}; + use casper_types::{ + execution::ExecutionResult, testing::TestRng, BlockHash, CLValue, StoredValue, + }; #[test] fn uptime_roundtrip() { @@ -395,19 +374,6 @@ mod tests { bytesrepr::test_serialization_roundtrip(&LastProgress::new(Timestamp::random(rng))); } - #[test] - fn speculative_execution_result_roundtrip() { - let rng = &mut TestRng::new(); - if rng.gen_bool(0.5) { - bytesrepr::test_serialization_roundtrip(&SpeculativeExecutionResult::new(None)); - } else { - bytesrepr::test_serialization_roundtrip(&SpeculativeExecutionResult::new(Some(( - ExecutionResultV2::random(rng), - rng.random_vec(0..20), - )))); - } - } - #[test] fn get_trie_full_result_roundtrip() { let rng = &mut TestRng::new(); diff --git a/execution_engine/src/engine_state/deploy_item.rs b/execution_engine/src/engine_state/deploy_item.rs index de3b71673e..749771b60a 100644 --- a/execution_engine/src/engine_state/deploy_item.rs +++ b/execution_engine/src/engine_state/deploy_item.rs @@ -4,8 +4,6 @@ use std::collections::BTreeSet; use casper_types::{account::AccountHash, Deploy, DeployHash, ExecutableDeployItem}; -type GasPrice = u64; - /// Definition of a deploy with all the details that make it possible to execute it. /// Corresponds to the similarly-named IPC protobuf message. #[derive(Clone, PartialEq, Eq, Debug)] @@ -18,7 +16,7 @@ pub struct DeployItem { /// Payment code. pub payment: ExecutableDeployItem, /// Gas price specified for this deploy by the user. - pub gas_price: GasPrice, + pub gas_price: u8, /// List of accounts that signed this deploy. pub authorization_keys: BTreeSet, /// A unique identifier of the deploy. @@ -32,7 +30,7 @@ impl DeployItem { address: AccountHash, session: ExecutableDeployItem, payment: ExecutableDeployItem, - gas_price: GasPrice, + gas_price: u8, authorization_keys: BTreeSet, deploy_hash: DeployHash, ) -> Self { @@ -65,7 +63,7 @@ impl From for DeployItem { address, deploy.session().clone(), deploy.payment().clone(), - deploy.header().gas_price(), + deploy.header().gas_price() as u8, authorization_keys, DeployHash::new(*deploy.hash().inner()), ) diff --git a/execution_engine/src/engine_state/engine_config.rs b/execution_engine/src/engine_state/engine_config.rs index 8462392d73..f362aced80 100644 --- a/execution_engine/src/engine_state/engine_config.rs +++ b/execution_engine/src/engine_state/engine_config.rs @@ -7,8 +7,8 @@ use num_rational::Ratio; use num_traits::One; use casper_types::{ - account::AccountHash, FeeHandling, PublicKey, RefundHandling, SystemConfig, WasmConfig, - DEFAULT_REFUND_HANDLING, + account::AccountHash, FeeHandling, ProtocolVersion, PublicKey, RefundHandling, SystemConfig, + TimeDiff, WasmConfig, DEFAULT_FEE_HANDLING, DEFAULT_REFUND_HANDLING, }; /// Default value for a maximum query depth configuration option. @@ -40,17 +40,18 @@ pub const DEFAULT_MAX_DELEGATORS_PER_VALIDATOR: u32 = 1200; pub const DEFAULT_ALLOW_AUCTION_BIDS: bool = true; /// Default value for allowing unrestricted transfers. pub const DEFAULT_ALLOW_UNRESTRICTED_TRANSFERS: bool = true; - -/// Default fee handling. -pub const DEFAULT_FEE_HANDLING: FeeHandling = FeeHandling::PayToProposer; /// Default compute rewards. pub const DEFAULT_COMPUTE_REWARDS: bool = true; +/// Default protocol version. +pub const DEFAULT_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V2_0_0; +/// Default period for balance holds to decay (currently 24 hours). +pub const DEFAULT_BALANCE_HOLD_INTERVAL: TimeDiff = TimeDiff::from_seconds(24 * 60 * 60); /// The runtime configuration of the execution engine #[derive(Debug, Clone)] pub struct EngineConfig { /// Maximum number of associated keys (i.e. map of - /// [`AccountHash`](casper_types::account::AccountHash)s to + /// [`AccountHash`](AccountHash)s to /// [`Weight`](casper_types::account::Weight)s) for a single account. max_associated_keys: u32, max_runtime_call_stack_height: u32, @@ -62,6 +63,7 @@ pub struct EngineConfig { max_delegators_per_validator: u32, wasm_config: WasmConfig, system_config: SystemConfig, + protocol_version: ProtocolVersion, /// A private network specifies a list of administrative accounts. pub(crate) administrative_accounts: BTreeSet, /// Auction entrypoints such as "add_bid" or "delegate" are disabled if this flag is set to @@ -79,6 +81,8 @@ pub struct EngineConfig { pub(crate) fee_handling: FeeHandling, /// Compute auction rewards. pub(crate) compute_rewards: bool, + /// The period over which balance holds decay. + pub(crate) balance_hold_interval: TimeDiff, } impl Default for EngineConfig { @@ -98,6 +102,8 @@ impl Default for EngineConfig { refund_handling: DEFAULT_REFUND_HANDLING, fee_handling: DEFAULT_FEE_HANDLING, compute_rewards: DEFAULT_COMPUTE_REWARDS, + protocol_version: DEFAULT_PROTOCOL_VERSION, + balance_hold_interval: DEFAULT_BALANCE_HOLD_INTERVAL, } } } @@ -123,6 +129,11 @@ impl EngineConfig { &self.system_config } + /// Returns the current protocol version. + pub fn protocol_version(&self) -> ProtocolVersion { + self.protocol_version + } + /// Returns the minimum delegation amount in motes. pub fn minimum_delegation_amount(&self) -> u64 { self.minimum_delegation_amount @@ -164,8 +175,8 @@ impl EngineConfig { } /// Returns the engine config's refund ratio. - pub fn refund_handling(&self) -> &RefundHandling { - &self.refund_handling + pub fn refund_handling(&self) -> RefundHandling { + self.refund_handling } /// Returns the engine config's fee handling strategy. @@ -177,6 +188,15 @@ impl EngineConfig { pub fn compute_rewards(&self) -> bool { self.compute_rewards } + + /// Sets the protocol version of the config. + /// + /// NOTE: This is only useful to the WasmTestBuilder for emulating a network upgrade, and hence + /// is subject to change or deletion without notice. + #[doc(hidden)] + pub fn set_protocol_version(&mut self, protocol_version: ProtocolVersion) { + self.protocol_version = protocol_version; + } } /// A builder for an [`EngineConfig`]. @@ -194,12 +214,14 @@ pub struct EngineConfigBuilder { max_delegators_per_validator: Option, wasm_config: Option, system_config: Option, + protocol_version: Option, administrative_accounts: Option>, allow_auction_bids: Option, allow_unrestricted_transfers: Option, refund_handling: Option, fee_handling: Option, compute_rewards: Option, + balance_hold_interval: Option, } impl EngineConfigBuilder { @@ -259,6 +281,12 @@ impl EngineConfigBuilder { self } + /// Sets the protocol version. + pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self { + self.protocol_version = Some(protocol_version); + self + } + /// Sets the maximum wasm stack height config option. pub fn with_wasm_max_stack_height(mut self, wasm_stack_height: u32) -> Self { let wasm_config = self.wasm_config.get_or_insert_with(WasmConfig::default); @@ -302,7 +330,7 @@ impl EngineConfigBuilder { "refund ratio should be in the range of [0, 1]" ); } - RefundHandling::None => { + RefundHandling::NoRefund => { //noop } } @@ -323,6 +351,12 @@ impl EngineConfigBuilder { self } + /// Sets balance hold interval config option. + pub fn balance_hold_interval(mut self, balance_hold_interval: TimeDiff) -> Self { + self.balance_hold_interval = Some(balance_hold_interval); + self + } + /// Builds a new [`EngineConfig`] object. pub fn build(self) -> EngineConfig { let max_associated_keys = self @@ -336,6 +370,7 @@ impl EngineConfigBuilder { .unwrap_or(DEFAULT_MINIMUM_DELEGATION_AMOUNT); let wasm_config = self.wasm_config.unwrap_or_default(); let system_config = self.system_config.unwrap_or_default(); + let protocol_version = self.protocol_version.unwrap_or(DEFAULT_PROTOCOL_VERSION); let administrative_accounts = { self.administrative_accounts .unwrap_or_default() @@ -362,6 +397,9 @@ impl EngineConfigBuilder { .max_delegators_per_validator .unwrap_or(DEFAULT_MAX_DELEGATORS_PER_VALIDATOR); let compute_rewards = self.compute_rewards.unwrap_or(DEFAULT_COMPUTE_REWARDS); + let balance_hold_interval = self + .balance_hold_interval + .unwrap_or(DEFAULT_BALANCE_HOLD_INTERVAL); EngineConfig { max_associated_keys, @@ -369,6 +407,7 @@ impl EngineConfigBuilder { minimum_delegation_amount, wasm_config, system_config, + protocol_version, administrative_accounts, allow_auction_bids, allow_unrestricted_transfers, @@ -378,6 +417,7 @@ impl EngineConfigBuilder { vesting_schedule_period_millis, max_delegators_per_validator, compute_rewards, + balance_hold_interval, } } } diff --git a/execution_engine/src/engine_state/error.rs b/execution_engine/src/engine_state/error.rs index 0cf5ad0b12..16adedd82e 100644 --- a/execution_engine/src/engine_state/error.rs +++ b/execution_engine/src/engine_state/error.rs @@ -2,18 +2,10 @@ use datasize::DataSize; use thiserror::Error; -use casper_storage::{ - global_state::{self, state::CommitError}, - system::{ - genesis::GenesisError, protocol_upgrade::ProtocolUpgradeError, transfer::TransferError, - }, - tracking_copy::TrackingCopyError, -}; -use casper_types::{ - account::AccountHash, binary_port, bytesrepr, system::mint, ApiError, Digest, Key, KeyTag, - PackageHash, ProtocolVersion, -}; +use casper_storage::{system::transfer::TransferError, tracking_copy::TrackingCopyError}; +use casper_types::{bytesrepr, system::mint, ApiError, Digest, Key, ProtocolVersion}; +use super::InvalidRequest; use crate::{ execution::ExecError, runtime::{stack, PreprocessingError}, @@ -29,24 +21,12 @@ pub enum Error { /// Protocol version used in the deploy is invalid. #[error("Invalid protocol version: {0}")] InvalidProtocolVersion(ProtocolVersion), - /// Genesis error. - #[error("{0:?}")] - Genesis(Box), /// WASM preprocessing error. #[error("Wasm preprocessing error: {0}")] WasmPreprocessing(#[from] PreprocessingError), - /// WASM serialization error. - #[error("Wasm serialization error: {0:?}")] - WasmSerialization(#[from] casper_wasm::SerializationError), /// Contract execution error. #[error(transparent)] Exec(ExecError), - /// Storage error. - #[error("Storage error: {0}")] - Storage(#[from] global_state::error::Error), - /// Authorization error. - #[error("Authorization failure: not authorized.")] - Authorization, /// Payment code provided insufficient funds for execution. #[error("Insufficient payment")] InsufficientPayment, @@ -66,59 +46,17 @@ pub enum Error { #[error("Mint error: {0}")] Mint(String), /// Invalid key variant. - #[error("Unsupported key type")] - InvalidKeyVariant, - /// Protocol upgrade error. - #[error("Protocol upgrade error: {0}")] - ProtocolUpgrade(#[from] ProtocolUpgradeError), + #[error("Unsupported key type: {0}")] + InvalidKeyVariant(Key), /// Invalid deploy item variant. #[error("Unsupported deploy item variant: {0}")] InvalidDeployItemVariant(String), - /// Commit error. - #[error(transparent)] - CommitError(#[from] CommitError), - /// Missing system contract registry. - #[error("Missing system contract registry")] - MissingSystemContractRegistry, /// Missing system contract hash. #[error("Missing system contract hash: {0}")] MissingSystemContractHash(String), - /// Missing checksum registry. - #[error("Missing checksum registry")] - MissingChecksumRegistry, /// An attempt to push to the runtime stack while already at the maximum height. #[error("Runtime stack overflow")] RuntimeStackOverflow, - /// Failed to get the set of keys matching the specified tag. - #[error("Failed to get keys of kind: {0:?}")] - FailedToGetKeys(KeyTag), - /// Failed to get the purses stored under Key::Withdraw - #[error("Failed to get stored values under withdraws")] - FailedToGetStoredWithdraws, - /// Failed to convert the StoredValue into WithdrawPurse. - #[error("Failed to convert the stored value to a withdraw purse")] - FailedToGetWithdrawPurses, - /// Failed to retrieve the unbonding delay from the auction state. - #[error("Failed to retrieve the unbonding delay from the auction state")] - FailedToRetrieveUnbondingDelay, - /// Failed to retrieve the current EraId from the auction state. - #[error("Failed to retrieve the era_id from the auction state")] - FailedToRetrieveEraId, - /// Failed to put a trie node into global state because some of its children were missing. - #[error("Failed to put a trie into global state because some of its children were missing")] - MissingTrieNodeChildren(Vec), - /// Failed to retrieve contract record by a given account hash. - #[error("Failed to retrieve contract by account hash {0}")] - MissingContractByAccountHash(AccountHash), - /// Failed to retrieve the entity's package - #[error("Failed to retrieve the entity package as {0}")] - MissingEntityPackage(PackageHash), - /// Failed to retrieve accumulation purse from handle payment system contract. - #[error("Failed to retrieve accumulation purse from the handle payment contract")] - FailedToRetrieveAccumulationPurse, - /// Failed to prune listed keys. - #[error("Pruning attempt failed.")] - FailedToPrune(Vec), /// Storage error. #[error("Tracking copy error: {0}")] TrackingCopy(TrackingCopyError), @@ -128,6 +66,9 @@ pub enum Error { /// Deprecated functionality. #[error("Deprecated: {0}")] Deprecated(String), + /// Could not derive a valid item to execute. + #[error("Invalid executable item: {0}")] + InvalidExecutableItem(#[from] InvalidRequest), } impl Error { @@ -170,12 +111,6 @@ impl From for Error { } } -impl From> for Error { - fn from(genesis_error: Box) -> Self { - Self::Genesis(genesis_error) - } -} - impl From for Error { fn from(_: stack::RuntimeStackOverflow) -> Self { Self::RuntimeStackOverflow @@ -188,19 +123,6 @@ impl From for Error { } } -impl From for binary_port::ErrorCode { - fn from(err: Error) -> Self { - match err { - Error::RootNotFound(_) => binary_port::ErrorCode::RootNotFound, - Error::InvalidDeployItemVariant(_) => binary_port::ErrorCode::InvalidDeployItemVariant, - Error::WasmPreprocessing(_) => binary_port::ErrorCode::WasmPreprocessing, - Error::InvalidProtocolVersion(_) => binary_port::ErrorCode::UnsupportedProtocolVersion, - Error::Deploy => binary_port::ErrorCode::InvalidTransaction, - _ => binary_port::ErrorCode::InternalError, - } - } -} - impl DataSize for Error { const IS_DYNAMIC: bool = true; diff --git a/execution_engine/src/engine_state/execute_request.rs b/execution_engine/src/engine_state/execute_request.rs deleted file mode 100644 index 4d51122dc1..0000000000 --- a/execution_engine/src/engine_state/execute_request.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Code supporting an execution request. -use std::mem; - -use casper_types::{Digest, ProtocolVersion, PublicKey, SecretKey}; - -use super::deploy_item::DeployItem; - -/// Represents an execution request that can contain multiple deploys. -#[derive(Debug)] -pub struct ExecuteRequest { - /// State root hash of the global state in which the deploys will be executed. - pub parent_state_hash: Digest, - /// Block time represented as a unix timestamp. - pub block_time: u64, - /// List of deploys that will be executed as part of this request. - pub deploys: Vec, - /// Protocol version used to execute deploys from the list. - pub protocol_version: ProtocolVersion, - /// The owner of the node that proposed the block containing this request. - pub proposer: PublicKey, -} - -impl ExecuteRequest { - /// Creates new execute request. - pub fn new( - parent_state_hash: Digest, - block_time: u64, - deploys: Vec, - protocol_version: ProtocolVersion, - proposer: PublicKey, - ) -> Self { - Self { - parent_state_hash, - block_time, - deploys, - protocol_version, - proposer, - } - } - - /// Returns deploys, and overwrites the existing value with empty list. - pub fn take_deploys(&mut self) -> Vec { - mem::take(&mut self.deploys) - } - - /// Returns list of deploys. - pub fn deploys(&self) -> &Vec { - &self.deploys - } -} - -impl Default for ExecuteRequest { - fn default() -> Self { - let proposer_secret_key = - SecretKey::ed25519_from_bytes([0; SecretKey::ED25519_LENGTH]).unwrap(); - let proposer = PublicKey::from(&proposer_secret_key); - Self { - parent_state_hash: Digest::hash([]), - block_time: 0, - deploys: vec![], - protocol_version: Default::default(), - proposer, - } - } -} diff --git a/execution_engine/src/engine_state/execution_kind.rs b/execution_engine/src/engine_state/execution_kind.rs index a6ea6eb01c..a37f241f50 100644 --- a/execution_engine/src/engine_state/execution_kind.rs +++ b/execution_engine/src/engine_state/execution_kind.rs @@ -1,121 +1,110 @@ //! Units of execution. -use std::{cell::RefCell, rc::Rc}; - use casper_storage::{ global_state::{error::Error as GlobalStateError, state::StateReader}, tracking_copy::{TrackingCopy, TrackingCopyExt}, }; use casper_types::{ - addressable_entity::NamedKeys, bytesrepr::Bytes, AddressableEntityHash, EntityVersionKey, - ExecutableDeployItem, Key, Package, PackageHash, Phase, ProtocolVersion, StoredValue, + addressable_entity::NamedKeys, bytesrepr::Bytes, AddressableEntityHash, EntityVersionKey, Key, + PackageHash, ProtocolVersion, StoredValue, TransactionInvocationTarget, TransactionSessionKind, }; -use crate::{engine_state::error::Error, execution::ExecError}; +use super::{Error, ExecutableItem}; +use crate::execution::ExecError; /// The type of execution about to be performed. #[derive(Clone, Debug)] -pub(crate) enum ExecutionKind { - /// Wasm bytes. - Module(Bytes), +pub(crate) enum ExecutionKind<'a> { + /// Standard (non-specialized) Wasm bytes related to a transaction of version 1 or later. + Standard(&'a Bytes), + /// Wasm bytes which install a stored entity. + Installer(&'a Bytes), + /// Wasm bytes which upgrade a stored entity. + Upgrader(&'a Bytes), + /// Wasm bytes which don't call any stored entity. + Isolated(&'a Bytes), /// Stored contract. - Contract { + Stored { /// AddressableEntity's hash. entity_hash: AddressableEntityHash, - /// Entry point's name. - entry_point_name: String, + /// Entry point. + entry_point: String, }, + /// Standard (non-specialized) Wasm bytes related to a `Deploy`. + /// + /// This is equivalent to the `Standard` variant with the exception that this kind will be + /// allowed to install or upgrade stored entities to retain existing (pre-node 2.0) behavior. + Deploy(&'a Bytes), } -impl ExecutionKind { - /// Returns a new module variant of `ExecutionKind`. - pub fn new_module(module_bytes: Bytes) -> Self { - ExecutionKind::Module(module_bytes) - } - - /// Returns a new contract variant of `ExecutionKind`. - pub fn new_addressable_entity( - entity_hash: AddressableEntityHash, - entry_point_name: String, - ) -> Self { - ExecutionKind::Contract { - entity_hash, - entry_point_name, +impl<'a> ExecutionKind<'a> { + pub(crate) fn new( + tracking_copy: &mut TrackingCopy, + named_keys: &NamedKeys, + executable_item: &'a ExecutableItem, + entry_point: String, + protocol_version: ProtocolVersion, + ) -> Result + where + R: StateReader, + { + match executable_item { + ExecutableItem::Invocation(target) => Self::new_stored( + tracking_copy, + named_keys, + target, + entry_point, + protocol_version, + ), + ExecutableItem::PaymentBytes(module_bytes) + | ExecutableItem::SessionBytes { + kind: TransactionSessionKind::Standard, + module_bytes, + } => Ok(ExecutionKind::Standard(module_bytes)), + ExecutableItem::SessionBytes { + kind: TransactionSessionKind::Installer, + module_bytes, + } => Ok(ExecutionKind::Installer(module_bytes)), + ExecutableItem::SessionBytes { + kind: TransactionSessionKind::Upgrader, + module_bytes, + } => Ok(ExecutionKind::Upgrader(module_bytes)), + ExecutableItem::SessionBytes { + kind: TransactionSessionKind::Isolated, + module_bytes, + } => Ok(ExecutionKind::Isolated(module_bytes)), + ExecutableItem::LegacyDeploy(module_bytes) => Ok(ExecutionKind::Deploy(module_bytes)), } } - /// Returns all the details necessary for execution. - /// - /// This object is generated based on information provided by [`ExecutableDeployItem`]. - pub fn new( - tracking_copy: Rc>>, + fn new_stored( + tracking_copy: &mut TrackingCopy, named_keys: &NamedKeys, - executable_deploy_item: ExecutableDeployItem, - protocol_version: &ProtocolVersion, - phase: Phase, - ) -> Result + target: &TransactionInvocationTarget, + entry_point: String, + protocol_version: ProtocolVersion, + ) -> Result where R: StateReader, { - let package: Package; - - let is_payment_phase = phase == Phase::Payment; - - match executable_deploy_item { - ExecutableDeployItem::Transfer { .. } => { - Err(Error::InvalidDeployItemVariant("Transfer".into())) - } - ExecutableDeployItem::ModuleBytes { module_bytes, .. } - if module_bytes.is_empty() && is_payment_phase => - { - Err(Error::InvalidDeployItemVariant( - "Empty module bytes for custom payment".into(), - )) - } - ExecutableDeployItem::ModuleBytes { module_bytes, .. } => { - Ok(ExecutionKind::new_module(module_bytes)) - } - ExecutableDeployItem::StoredContractByHash { - hash, entry_point, .. - } => Ok(ExecutionKind::new_addressable_entity(hash, entry_point)), - ExecutableDeployItem::StoredContractByName { - name, entry_point, .. - } => { + let entity_hash = match target { + TransactionInvocationTarget::ByHash(addr) => AddressableEntityHash::new(*addr), + TransactionInvocationTarget::ByName(alias) => { let entity_key = named_keys - .get(&name) - .cloned() - .ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(name.to_string())))?; + .get(alias) + .ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(alias.clone())))?; - let entity_hash = match entity_key { - Key::Hash(hash) => AddressableEntityHash::new(hash), + match entity_key { + Key::Hash(hash) => AddressableEntityHash::new(*hash), Key::AddressableEntity(entity_addr) => { AddressableEntityHash::new(entity_addr.value()) } - _ => return Err(Error::InvalidKeyVariant), - }; - - Ok(ExecutionKind::new_addressable_entity( - entity_hash, - entry_point, - )) + _ => return Err(Error::InvalidKeyVariant(*entity_key)), + } } - ExecutableDeployItem::StoredVersionedContractByName { - name, - version, - entry_point, - .. - } => { - let package_key = named_keys - .get(&name) - .cloned() - .ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(name.to_string())))?; - - let package_hash = match package_key { - Key::Hash(hash) | Key::Package(hash) => PackageHash::new(hash), - _ => return Err(Error::InvalidKeyVariant), - }; - - package = tracking_copy.borrow_mut().get_package(package_hash)?; + TransactionInvocationTarget::ByPackageHash { addr, version } => { + let package_hash = PackageHash::from(*addr); + let package = tracking_copy.get_package(package_hash)?; let maybe_version_key = version.map(|ver| EntityVersionKey::new(protocol_version.value().major, ver)); @@ -129,31 +118,33 @@ impl ExecutionKind { entity_version_key, ))); } + if !package.is_version_enabled(entity_version_key) { return Err(Error::Exec(ExecError::DisabledEntityVersion( entity_version_key, ))); } - let looked_up_entity_hash: AddressableEntityHash = package + *package .lookup_entity_hash(entity_version_key) - .ok_or(Error::Exec(ExecError::MissingEntityVersion( + .ok_or(Error::Exec(ExecError::InvalidEntityVersion( entity_version_key, )))? - .to_owned(); - - Ok(ExecutionKind::new_addressable_entity( - looked_up_entity_hash, - entry_point, - )) } - ExecutableDeployItem::StoredVersionedContractByHash { - hash: package_hash, + TransactionInvocationTarget::ByPackageName { + name: alias, version, - entry_point, - .. } => { - package = tracking_copy.borrow_mut().get_package(package_hash)?; + let package_key = named_keys + .get(alias) + .ok_or_else(|| Error::Exec(ExecError::NamedKeyNotFound(alias.to_string())))?; + + let package_hash = match package_key { + Key::Hash(hash) | Key::Package(hash) => PackageHash::new(*hash), + _ => return Err(Error::InvalidKeyVariant(*package_key)), + }; + + let package = tracking_copy.get_package(package_hash)?; let maybe_version_key = version.map(|ver| EntityVersionKey::new(protocol_version.value().major, ver)); @@ -174,18 +165,16 @@ impl ExecutionKind { ))); } - let looked_up_entity_hash = - *package - .lookup_entity_hash(entity_version_key) - .ok_or(Error::Exec(ExecError::MissingEntityVersion( - entity_version_key, - )))?; - - Ok(ExecutionKind::new_addressable_entity( - looked_up_entity_hash, - entry_point, - )) + *package + .lookup_entity_hash(entity_version_key) + .ok_or(Error::Exec(ExecError::InvalidEntityVersion( + entity_version_key, + )))? } - } + }; + Ok(ExecutionKind::Stored { + entity_hash, + entry_point, + }) } } diff --git a/execution_engine/src/engine_state/execution_result.rs b/execution_engine/src/engine_state/execution_result.rs deleted file mode 100644 index 366519cc91..0000000000 --- a/execution_engine/src/engine_state/execution_result.rs +++ /dev/null @@ -1,621 +0,0 @@ -//! Outcome of an `ExecutionRequest`. - -use std::collections::VecDeque; -use tracing::{debug, trace}; - -use casper_storage::data_access_layer::TransferResult; -use casper_types::{ - bytesrepr::FromBytes, - contract_messages::Messages, - execution::{Effects, ExecutionResultV2 as TypesExecutionResult, TransformKindV2, TransformV2}, - CLTyped, CLValue, Gas, Key, Motes, StoredValue, TransferAddr, -}; - -use super::Error; -use crate::execution::ExecError; - -/// Represents the result of an execution specified by -/// [`crate::engine_state::ExecuteRequest`]. -#[derive(Clone, Debug)] -pub enum ExecutionResult { - /// An error condition that happened during execution - Failure { - /// Error causing this `Failure` variant. - error: Error, - /// List of transfers that happened during execution up to the point of the failure. - transfers: Vec, - /// Gas consumed up to the point of the failure. - cost: Gas, - /// Execution effects. - effects: Effects, - /// Messages emitted during execution. - messages: Messages, - }, - /// Execution was finished successfully - Success { - /// List of transfers. - transfers: Vec, - /// Gas cost. - cost: Gas, - /// Execution effects. - effects: Effects, - /// Messages emitted during execution. - messages: Messages, - }, -} - -impl ExecutionResult { - /// Constructs [ExecutionResult::Failure] that has 0 cost and no effects. - /// This is the case for failures that we can't (or don't want to) charge - /// for, like `PreprocessingError` or `InvalidNonce`. - pub fn precondition_failure(error: Error) -> ExecutionResult { - ExecutionResult::Failure { - error, - transfers: Vec::default(), - cost: Gas::default(), - effects: Effects::new(), - messages: Vec::default(), - } - } - - /// Returns `true` if this is a successful variant. - pub fn is_success(&self) -> bool { - match self { - ExecutionResult::Failure { .. } => false, - ExecutionResult::Success { .. } => true, - } - } - - /// Returns `true` if this is a failure variant. - pub fn is_failure(&self) -> bool { - match self { - ExecutionResult::Failure { .. } => true, - ExecutionResult::Success { .. } => false, - } - } - - /// Returns `true` if this is a precondition failure. - /// - /// Precondition variant is further described as an execution failure which does not have any - /// effects, and has a gas cost of 0. - pub fn has_precondition_failure(&self) -> bool { - match self { - ExecutionResult::Failure { cost, effects, .. } => { - cost.value() == 0.into() && effects.is_empty() - } - ExecutionResult::Success { .. } => false, - } - } - - /// Returns gas cost of execution regardless of variant. - pub fn cost(&self) -> Gas { - match self { - ExecutionResult::Failure { cost, .. } => *cost, - ExecutionResult::Success { cost, .. } => *cost, - } - } - - /// Returns list of transfers regardless of variant. - pub fn transfers(&self) -> &Vec { - match self { - ExecutionResult::Failure { transfers, .. } => transfers, - ExecutionResult::Success { transfers, .. } => transfers, - } - } - - /// The ordered execution effects regardless of variant. - pub fn effects(&self) -> &Effects { - match self { - ExecutionResult::Failure { effects, .. } | ExecutionResult::Success { effects, .. } => { - effects - } - } - } - - /// Returns a new execution result with updated gas cost. - /// - /// This method preserves the [`ExecutionResult`] variant and updates the cost field - /// only. - pub fn with_cost(self, cost: Gas) -> Self { - match self { - ExecutionResult::Failure { - error, - transfers, - effects, - messages, - .. - } => ExecutionResult::Failure { - error, - transfers, - cost, - effects, - messages, - }, - ExecutionResult::Success { - transfers, - effects, - messages, - .. - } => ExecutionResult::Success { - transfers, - cost, - effects, - messages, - }, - } - } - - /// Returns a new execution result with updated transfers field. - /// - /// This method preserves the [`ExecutionResult`] variant and updates the - /// `transfers` field only. - pub fn with_transfers(self, transfers: Vec) -> Self { - match self { - ExecutionResult::Failure { - error, - cost, - effects, - messages, - .. - } => ExecutionResult::Failure { - error, - transfers, - cost, - effects, - messages, - }, - ExecutionResult::Success { - cost, - effects, - messages, - .. - } => ExecutionResult::Success { - transfers, - cost, - effects, - messages, - }, - } - } - - /// Returns a new execution result with updated execution effects. - /// - /// This method preserves the [`ExecutionResult`] variant and updates the - /// `effects` field only. - pub fn with_effects(self, effects: Effects) -> Self { - match self { - ExecutionResult::Failure { - error, - transfers, - cost, - effects: _, - messages, - } => ExecutionResult::Failure { - error, - transfers, - cost, - effects, - messages, - }, - ExecutionResult::Success { - transfers, - cost, - effects: _, - messages, - } => ExecutionResult::Success { - transfers, - cost, - effects, - messages, - }, - } - } - - /// Returns error value, if possible. - /// - /// Returns a reference to a wrapped [`super::Error`] - /// instance if the object is a failure variant. - pub fn as_error(&self) -> Option<&Error> { - match self { - ExecutionResult::Failure { error, .. } => Some(error), - ExecutionResult::Success { .. } => None, - } - } - - /// Consumes [`ExecutionResult`] instance and optionally returns - /// [`super::Error`] instance for - /// [`ExecutionResult::Failure`] variant. - pub fn take_error(self) -> Option { - match self { - ExecutionResult::Failure { error, .. } => Some(error), - ExecutionResult::Success { .. } => None, - } - } - - /// Checks the transfer status of a payment code. - /// - /// This method converts the gas cost of the execution result into motes using supplied - /// `gas_price`, and then a check is made to ensure that user deposited enough funds in the - /// payment purse (in motes) to cover the execution of a payment code. - /// - /// Returns `None` if user deposited enough funds in payment purse and the execution result was - /// a success variant, otherwise a wrapped [`ForcedTransferResult`] that indicates an error - /// condition. - pub fn check_forced_transfer( - &self, - payment_purse_balance: Motes, - gas_price: u64, - ) -> Option { - let payment_result_cost = match Motes::from_gas(self.cost(), gas_price) { - Some(cost) => cost, - None => return Some(ForcedTransferResult::GasConversionOverflow), - }; - // payment_code_spec_3_b_ii: if (balance of handle payment pay purse) < (gas spent during - // payment code execution) * gas_price, no session - let insufficient_balance_to_continue = payment_purse_balance < payment_result_cost; - - match self { - ExecutionResult::Success { .. } if insufficient_balance_to_continue => { - // payment_code_spec_4: insufficient payment - Some(ForcedTransferResult::InsufficientPayment) - } - ExecutionResult::Success { .. } => { - // payment_code_spec_3_b_ii: continue execution - None - } - ExecutionResult::Failure { .. } => { - // payment_code_spec_3_a: report payment error in the deploy response - Some(ForcedTransferResult::PaymentFailure) - } - } - } - - /// Creates a new payment code error. - /// - /// The method below creates an [`ExecutionResult`] with precomputed effects of a - /// "finalize_payment". - /// - /// The effects that are produced as part of this process would subract `max_payment_cost` from - /// account's main purse, and add `max_payment_cost` to proposer account's balance. - pub fn new_payment_code_error( - error: Error, - max_payment_cost: Motes, - account_main_purse_balance: Motes, - gas_cost: Gas, - account_main_purse_balance_key: Key, - proposer_main_purse_balance_key: Key, - ) -> Result { - let new_balance = account_main_purse_balance - .checked_sub(max_payment_cost) - .ok_or(Error::InsufficientPayment)?; - let new_balance_value = - StoredValue::CLValue(CLValue::from_t(new_balance.value()).map_err(ExecError::from)?); - let mut effects = Effects::new(); - effects.push(TransformV2::new( - account_main_purse_balance_key.normalize(), - TransformKindV2::Write(new_balance_value), - )); - effects.push(TransformV2::new( - proposer_main_purse_balance_key.normalize(), - TransformKindV2::AddUInt512(max_payment_cost.value()), - )); - let transfers = Vec::default(); - Ok(ExecutionResult::Failure { - error, - effects, - transfers, - cost: gas_cost, - messages: Vec::default(), - }) - } - - /// Returns a wrapped `ret` by consuming object. - pub(crate) fn take_with_ret(self, ret: T) -> (Option, Self) { - (Some(ret), self) - } - - /// Returns a self and has a return type compatible with [`ExecutionResult::take_with_ret`]. - pub(crate) fn take_without_ret(self) -> (Option, Self) { - (None, self) - } - - /// A temporary measure to keep things functioning mid-refactor. - #[allow(clippy::result_unit_err)] - pub fn from_transfer_result(transfer_result: TransferResult, cost: Gas) -> Result { - match transfer_result { - TransferResult::RootNotFound => { - Err(()) - } - // native transfer is auto-commit...but execution results does not currently allow - // for a post state hash to be returned. - TransferResult::Success { - transfers, effects, .. // post_state_hash - } => { - Ok(ExecutionResult::Success { - transfers, - cost, - effects, - messages: Messages::default(), - }) - } - TransferResult::Failure(te) => { - Ok(ExecutionResult::Failure { - error: Error::Transfer(te), - transfers: vec![], - cost, - effects: Effects::default(), // currently not returning effects on failure - messages: Messages::default(), - }) - } - } - } - - /// Should charge for wasm errors? - pub(crate) fn should_charge_for_errors_in_wasm(&self) -> bool { - match self { - ExecutionResult::Failure { - error, - transfers: _, - cost: _, - effects: _, - messages: _, - } => match error { - Error::Exec(err) => matches!( - err, - ExecError::WasmPreprocessing(_) | ExecError::UnsupportedWasmStart - ), - Error::WasmPreprocessing(_) | Error::WasmSerialization(_) => true, - _ => false, - }, - ExecutionResult::Success { .. } => false, - } - } - - /// Logs execution results. - pub fn log_execution_result(&self, preamble: &'static str) { - trace!("{}: {:?}", preamble, self); - match self { - ExecutionResult::Success { - transfers, - cost, - effects, - messages, - } => { - debug!( - %cost, - transfer_count = %transfers.len(), - transforms_count = %effects.len(), - messages_count = %messages.len(), - "{}: execution success", - preamble - ); - } - ExecutionResult::Failure { - error, - transfers, - cost, - effects, - messages, - } => { - debug!( - %error, - %cost, - transfer_count = %transfers.len(), - transforms_count = %effects.len(), - messages_count = %messages.len(), - "{}: execution failure", - preamble - ); - } - } - } -} - -/// A type alias that represents multiple execution results. -pub type ExecutionResults = VecDeque; - -/// Indicates the outcome of a transfer payment check. -pub enum ForcedTransferResult { - /// Payment code ran out of gas during execution - InsufficientPayment, - /// Gas conversion overflow - GasConversionOverflow, - /// Payment code execution resulted in an error - PaymentFailure, -} - -/// A versioned execution result and the messages produced by that execution. -pub struct ExecutionResultAndMessages { - /// Execution result - pub execution_result: TypesExecutionResult, - /// Messages emitted during execution - pub messages: Messages, -} - -impl From for ExecutionResultAndMessages { - fn from(execution_result: ExecutionResult) -> Self { - match execution_result { - ExecutionResult::Success { - transfers, - cost, - effects, - messages, - } => ExecutionResultAndMessages { - execution_result: TypesExecutionResult::Success { - effects, - transfers, - cost: cost.value(), - }, - messages, - }, - ExecutionResult::Failure { - error, - transfers, - cost, - effects, - messages, - } => ExecutionResultAndMessages { - execution_result: TypesExecutionResult::Failure { - effects, - transfers, - cost: cost.value(), - error_message: error.to_string(), - }, - messages, - }, - } - } -} - -/// Represents error conditions of an execution result builder. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ExecutionResultBuilderError { - /// Missing a payment execution result. - MissingPaymentExecutionResult, - /// Missing a session execution result. - MissingSessionExecutionResult, - /// Missing a finalize execution result. - MissingFinalizeExecutionResult, -} - -/// Builder object that will construct a final [`ExecutionResult`] given payment, session and -/// finalize [`ExecutionResult`]s. -#[derive(Default)] -pub struct ExecutionResultBuilder { - payment_execution_result: Option, - session_execution_result: Option, - finalize_execution_result: Option, -} - -impl ExecutionResultBuilder { - /// Creates new execution result builder. - pub fn new() -> ExecutionResultBuilder { - ExecutionResultBuilder::default() - } - - /// Sets a payment execution result. - pub fn set_payment_execution_result(&mut self, payment_result: ExecutionResult) -> &mut Self { - self.payment_execution_result = Some(payment_result); - self - } - - /// Sets a session execution result. - pub fn set_session_execution_result( - &mut self, - session_execution_result: ExecutionResult, - ) -> &mut ExecutionResultBuilder { - self.session_execution_result = Some(session_execution_result); - self - } - - /// Sets a finalize execution result. - pub fn set_finalize_execution_result( - &mut self, - finalize_execution_result: ExecutionResult, - ) -> &mut ExecutionResultBuilder { - self.finalize_execution_result = Some(finalize_execution_result); - self - } - - /// Calculates the total gas cost of the execution result. - /// - /// Takes a payment execution result, and a session execution result and returns a sum. If - /// either a payment or session code is not specified then a 0 is used. - pub fn total_cost(&self) -> Gas { - let payment_cost = self - .payment_execution_result - .as_ref() - .map(ExecutionResult::cost) - .unwrap_or_default(); - let session_cost = self - .session_execution_result - .as_ref() - .map(ExecutionResult::cost) - .unwrap_or_default(); - // TODO: Make sure this code isn't in production, as, even though it's highly unlikely - // to happen, an integer overflow would be silently ignored in release builds. - // NOTE: This code should have been removed in the fix of #1968, where arithmetic - // operations on the Gas type were disabled. - payment_cost + session_cost - } - - /// Returns transfers from a session's execution result. - /// - /// If the session's execution result is not supplied then an empty [`Vec`] is returned. - pub fn transfers(&self) -> Vec { - self.session_execution_result - .as_ref() - .map(ExecutionResult::transfers) - .cloned() - .unwrap_or_default() - } - - /// Builds a final [`ExecutionResult`] based on session result, payment result and a - /// finalization result. - pub fn build(self) -> Result { - let mut error: Option = None; - let mut transfers = self.transfers(); - let cost = self.total_cost(); - - let (mut all_effects, mut all_messages) = match self.payment_execution_result { - Some(result @ ExecutionResult::Failure { .. }) => return Ok(result), - Some(ExecutionResult::Success { - effects, messages, .. - }) => (effects, messages), - None => return Err(ExecutionResultBuilderError::MissingPaymentExecutionResult), - }; - - // session_code_spec_3: only include session exec effects if there is no session - // exec error - match self.session_execution_result { - Some(ExecutionResult::Failure { - error: session_error, - transfers: session_transfers, - effects: _, - cost: _, - messages, - }) => { - error = Some(session_error); - transfers = session_transfers; - all_messages.extend(messages); - } - Some(ExecutionResult::Success { - effects, messages, .. - }) => { - all_effects.append(effects); - all_messages.extend(messages); - } - None => return Err(ExecutionResultBuilderError::MissingSessionExecutionResult), - }; - - match self.finalize_execution_result { - Some(ExecutionResult::Failure { .. }) => { - // payment_code_spec_5_a: Finalization Error should only ever be raised here - return Ok(ExecutionResult::precondition_failure(Error::Finalization)); - } - Some(ExecutionResult::Success { - effects, messages, .. - }) => { - all_effects.append(effects); - all_messages.extend(messages); - } - None => return Err(ExecutionResultBuilderError::MissingFinalizeExecutionResult), - } - - match error { - None => Ok(ExecutionResult::Success { - transfers, - cost, - effects: all_effects, - messages: all_messages, - }), - Some(error) => Ok(ExecutionResult::Failure { - error, - transfers, - cost, - effects: all_effects, - messages: all_messages, - }), - } - } -} diff --git a/execution_engine/src/engine_state/mod.rs b/execution_engine/src/engine_state/mod.rs index afd2e2f44a..4dd5d69608 100644 --- a/execution_engine/src/engine_state/mod.rs +++ b/execution_engine/src/engine_state/mod.rs @@ -2,49 +2,28 @@ pub mod deploy_item; pub mod engine_config; mod error; -pub mod execute_request; pub(crate) mod execution_kind; -pub mod execution_result; +mod wasm_v1; use std::{cell::RefCell, rc::Rc}; -use num_traits::Zero; use once_cell::sync::Lazy; -use tracing::error; use casper_storage::{ - data_access_layer::TransferRequest, global_state::state::StateProvider, - system::runtime_native::TransferConfig, - tracking_copy::{FeesPurseHandling, TrackingCopyEntityExt, TrackingCopyExt}, + tracking_copy::{TrackingCopyEntityExt, TrackingCopyError, TrackingCopyExt}, }; +use casper_types::U512; -use casper_types::{ - addressable_entity::EntityKind, - system::{ - handle_payment::{self}, - HANDLE_PAYMENT, - }, - BlockTime, DeployInfo, Digest, EntityAddr, ExecutableDeployItem, FeeHandling, Gas, Key, Motes, - Phase, ProtocolVersion, PublicKey, RuntimeArgs, StoredValue, TransactionHash, U512, -}; - -use crate::{ - engine_state::{execution_kind::ExecutionKind, execution_result::ExecutionResults}, - execution::{DirectSystemContractCall, ExecError, Executor}, - runtime::RuntimeStack, -}; - -pub use self::{ - deploy_item::DeployItem, - engine_config::{ - EngineConfig, EngineConfigBuilder, DEFAULT_MAX_QUERY_DEPTH, - DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT, - }, - error::Error, - execute_request::ExecuteRequest, - execution_result::{ExecutionResult, ForcedTransferResult}, +use crate::{execution::Executor, runtime::RuntimeStack}; +pub use deploy_item::DeployItem; +pub use engine_config::{ + EngineConfig, EngineConfigBuilder, DEFAULT_MAX_QUERY_DEPTH, + DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT, }; +pub use error::Error; +use execution_kind::ExecutionKind; +pub use wasm_v1::{ExecutableItem, InvalidRequest, WasmV1Request, WasmV1Result}; /// The maximum amount of motes that payment code execution can cost. pub const MAX_PAYMENT_AMOUNT: u64 = 2_500_000_000; @@ -57,20 +36,16 @@ pub static MAX_PAYMENT: Lazy = Lazy::new(|| U512::from(MAX_PAYMENT_AMOUNT) /// Gas/motes conversion rate of wasmless transfer cost is always 1 regardless of what user wants to /// pay. -pub const WASMLESS_TRANSFER_FIXED_GAS_PRICE: u64 = 1; +pub const WASMLESS_TRANSFER_FIXED_GAS_PRICE: u8 = 1; -/// Main implementation of an execution engine state. -/// -/// Takes an engine's configuration and a provider of a state (aka the global state) to operate on. -/// Methods implemented on this structure are the external API intended to be used by the users such -/// as the node, test framework, and others. +/// The public api of the v1 execution engine, as of protocol version 2.0.0 #[derive(Debug, Clone, Default)] pub struct ExecutionEngineV1 { config: EngineConfig, } impl ExecutionEngineV1 { - /// Creates new engine state. + /// Creates new execution engine. pub fn new(config: EngineConfig) -> ExecutionEngineV1 { ExecutionEngineV1 { config } } @@ -80,737 +55,94 @@ impl ExecutionEngineV1 { &self.config } - /// Runs a deploy execution request. - /// - /// For each deploy stored in the request it will execute it. - /// - /// Currently a special shortcut is taken to distinguish a native transfer, from a deploy. - /// - /// Return execution results which contains results from each deploy ran. - pub fn exec( + /// Executes wasm, and that's all. Does not commit or handle payment or anything else. + pub fn execute( &self, state_provider: &impl StateProvider, - mut exec_request: ExecuteRequest, - ) -> Result { - let deploys = exec_request.take_deploys(); - let mut results = ExecutionResults::with_capacity(deploys.len()); - - for deploy_item in deploys { - let result = match deploy_item.session { - ExecutableDeployItem::Transfer { .. } => self.transfer( - state_provider, - exec_request.protocol_version, - exec_request.parent_state_hash, - BlockTime::new(exec_request.block_time), - deploy_item, - ), - _ => self.deploy( - state_provider, - exec_request.protocol_version, - exec_request.parent_state_hash, - BlockTime::new(exec_request.block_time), - deploy_item, - exec_request.proposer.clone(), - ), - }; - match result { - Ok(result) => results.push_back(result), - Err(error) => { - return Err(error); - } - }; - } - - Ok(results) - } - - /// Executes a native transfer. - /// - /// Native transfers do not involve WASM at all, and also skip executing payment code. - /// Therefore this is the fastest and cheapest way to transfer tokens from account to account. - /// - /// Returns an [`ExecutionResult`] for a successful native transfer. - #[allow(clippy::too_many_arguments)] - fn transfer( - &self, - state_provider: &impl StateProvider, - protocol_version: ProtocolVersion, - prestate_hash: Digest, - blocktime: BlockTime, - deploy_item: DeployItem, - ) -> Result { - // leaving this method in place for now as a lot of tests rely on it. - // TODO: rewrite those tests to use the data access layer instead and - // then remove this method. - let deploy_hash = deploy_item.deploy_hash; - let transfer_config = TransferConfig::new( - self.config.administrative_accounts.clone(), - self.config.allow_unrestricted_transfers, - ); - - let fee_handling = self.config.fee_handling; - let refund_handling = self.config.refund_handling; - let vesting_schedule_period_millis = self.config.vesting_schedule_period_millis(); - let allow_auction_bids = self.config.allow_auction_bids; - let compute_rewards = self.config.compute_rewards; - let max_delegators_per_validator = self.config.max_delegators_per_validator(); - let minimum_delegation_amount = self.config.minimum_delegation_amount(); - - let native_runtime_config = casper_storage::system::runtime_native::Config::new( - transfer_config, - fee_handling, - refund_handling, - vesting_schedule_period_millis, - allow_auction_bids, - compute_rewards, - max_delegators_per_validator, - minimum_delegation_amount, - ); - let wasmless_transfer_gas = Gas::new(U512::from( - self.config().system_config().mint_costs().transfer, - )); - - let transaction_hash = TransactionHash::Deploy(deploy_hash); - - let transfer_req = TransferRequest::with_runtime_args( - native_runtime_config, - prestate_hash, - blocktime.value(), - protocol_version, + WasmV1Request { + state_hash, + block_time, transaction_hash, - deploy_item.address, - deploy_item.authorization_keys, - deploy_item.session.args().clone(), - wasmless_transfer_gas.value(), - ); - let transfer_result = state_provider.transfer(transfer_req); - ExecutionResult::from_transfer_result(transfer_result, wasmless_transfer_gas) - .map_err(|_| Error::RootNotFound(prestate_hash)) - } - - /// Executes a deploy. - /// - /// A deploy execution consists of running the payment code, which is expected to deposit funds - /// into the payment purse, and then running the session code with a specific gas limit. For - /// running payment code, we lock [`MAX_PAYMENT`] amount of motes from the user as collateral. - /// If both the payment code and the session code execute successfully, a fraction of the - /// unspent collateral will be transferred back to the proposer of the deploy, as specified - /// in the request. - /// - /// Returns [`ExecutionResult`], or an error condition. - #[allow(clippy::too_many_arguments)] - fn deploy( - &self, - state_provider: &impl StateProvider, - protocol_version: ProtocolVersion, - prestate_hash: Digest, - blocktime: BlockTime, - deploy_item: DeployItem, - proposer: PublicKey, - ) -> Result { - let tracking_copy = match state_provider.tracking_copy(prestate_hash) { - Err(gse) => return Ok(ExecutionResult::precondition_failure(Error::Storage(gse))), - Ok(None) => return Err(Error::RootNotFound(prestate_hash)), + gas_limit, + initiator_addr, + executable_item, + entry_point, + args, + authorization_keys, + phase, + }: WasmV1Request, + ) -> WasmV1Result { + // NOTE to core engineers: it is intended for the EE to ONLY execute wasm targeting the + // casper v1 virtual machine. it should not handle native behavior, database / global state + // interaction, payment processing, or anything other than its single function. + // A good deal of effort has been put into removing all such behaviors; please do not + // come along and start adding it back. + + let account_hash = initiator_addr.account_hash(); + let protocol_version = self.config.protocol_version(); + let tc = match state_provider.tracking_copy(state_hash) { Ok(Some(tracking_copy)) => Rc::new(RefCell::new(tracking_copy)), - }; - - let executor = Executor::new(self.config().clone()); - - let authorization_keys = deploy_item.authorization_keys; - let account_hash = deploy_item.address; - - if let Err(e) = tracking_copy - .borrow_mut() - .migrate_account(account_hash, protocol_version) - { - return Ok(ExecutionResult::precondition_failure(e.into())); - } - - // Get account from tracking copy - // validation_spec_3: account validity - let (entity, entity_hash) = { - match tracking_copy - .borrow_mut() - .get_authorized_addressable_entity( - protocol_version, - account_hash, - &authorization_keys, - &self.config().administrative_accounts, - ) { - Ok((addressable_entity, entity_hash)) => (addressable_entity, entity_hash), - Err(e) => return Ok(ExecutionResult::precondition_failure(e.into())), - } - }; - - let entity_kind = entity.entity_kind(); - - let entity_addr = EntityAddr::new_with_tag(entity_kind, entity_hash.value()); - - let entity_named_keys = match tracking_copy - .borrow_mut() - .get_named_keys(entity_addr) - .map_err(Into::into) - { - Ok(named_keys) => named_keys, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - }; - - let payment = deploy_item.payment; - let session = deploy_item.session; - - let deploy_hash = deploy_item.deploy_hash; - - let session_args = session.args().clone(); - - // Create session code `A` from provided session bytes - // validation_spec_1: valid wasm bytes - // we do this upfront as there is no reason to continue if session logic is invalid - let session_execution_kind = match ExecutionKind::new( - Rc::clone(&tracking_copy), - &entity_named_keys, - session, - &protocol_version, - Phase::Session, - ) { - Ok(execution_kind) => execution_kind, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - }; - - // Get account main purse balance key - // validation_spec_5: account main purse minimum balance - let entity_main_purse_key: Key = { - let account_key = Key::URef(entity.main_purse()); - match tracking_copy - .borrow_mut() - .get_purse_balance_key(account_key) - { - Ok(key) => key, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error.into())); - } + Ok(None) => return WasmV1Result::root_not_found(gas_limit, state_hash), + Err(gse) => { + return WasmV1Result::precondition_failure( + gas_limit, + Error::TrackingCopy(TrackingCopyError::Storage(gse)), + ) } }; - - // Get account main purse balance to enforce precondition and in case of forced - // transfer validation_spec_5: account main purse minimum balance - let account_main_purse_balance: Motes = match tracking_copy - .borrow_mut() - .get_purse_balance(entity_main_purse_key) - { - Ok(balance) => balance, - Err(error) => return Ok(ExecutionResult::precondition_failure(error.into())), - }; - - let max_payment_cost = Motes::new(*MAX_PAYMENT); - - // Enforce minimum main purse balance validation - // validation_spec_5: account main purse minimum balance - if account_main_purse_balance < max_payment_cost { - return Ok(ExecutionResult::precondition_failure( - Error::InsufficientPayment, - )); - } - - // Finalization is executed by system account (currently genesis account) - // payment_code_spec_5: system executes finalization - let system_addressable_entity = tracking_copy - .borrow_mut() - .get_addressable_entity_by_account_hash( + let (entity, entity_hash) = { + match tc.borrow_mut().get_authorized_addressable_entity( protocol_version, - PublicKey::System.to_account_hash(), - )?; - - // Get handle payment system contract details - // payment_code_spec_6: system contract validity - let system_contract_registry = tracking_copy.borrow_mut().get_system_entity_registry()?; - - let handle_payment_contract_hash = system_contract_registry - .get(HANDLE_PAYMENT) - .ok_or_else(|| { - error!("Missing system handle payment contract hash"); - Error::MissingSystemContractHash(HANDLE_PAYMENT.to_string()) - })?; - - let handle_payment_addr = - EntityAddr::new_system_entity_addr(handle_payment_contract_hash.value()); - - let handle_payment_named_keys = match tracking_copy - .borrow_mut() - .get_named_keys(handle_payment_addr) - .map_err(Into::into) - { - Ok(named_keys) => named_keys, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - }; - - // Get payment purse Key from handle payment contract - // payment_code_spec_6: system contract validity - let payment_purse_key = - match handle_payment_named_keys.get(handle_payment::PAYMENT_PURSE_KEY) { - Some(key) => *key, - None => return Ok(ExecutionResult::precondition_failure(Error::Deploy)), - }; - - let payment_purse_uref = payment_purse_key - .into_uref() - .ok_or(Error::InvalidKeyVariant)?; - - // [`ExecutionResultBuilder`] handles merging of multiple execution results - let mut execution_result_builder = execution_result::ExecutionResultBuilder::new(); - - let rewards_target_purse = { - let fees_purse_handling = match self.config.fee_handling { - FeeHandling::PayToProposer => { - FeesPurseHandling::ToProposer(proposer.to_account_hash()) - } - FeeHandling::None => FeesPurseHandling::None(payment_purse_uref), - FeeHandling::Accumulate => FeesPurseHandling::Accumulate, - FeeHandling::Burn => FeesPurseHandling::Burn, - }; - - match tracking_copy - .borrow_mut() - .fees_purse(protocol_version, fees_purse_handling) - { - Err(tce) => return Ok(ExecutionResult::precondition_failure(tce.into())), - Ok(purse) => purse, - } - }; - - let rewards_target_purse_balance_key = { - // Get reward purse Key from handle payment contract - // payment_code_spec_6: system contract validity - match tracking_copy - .borrow_mut() - .get_purse_balance_key(rewards_target_purse.into()) - { + account_hash, + &authorization_keys, + &self.config().administrative_accounts, + ) { + Ok((addressable_entity, entity_hash)) => (addressable_entity, entity_hash), Err(tce) => { - return Ok(ExecutionResult::precondition_failure(tce.into())); + return WasmV1Result::precondition_failure(gas_limit, Error::TrackingCopy(tce)) } - Ok(key) => key, } }; - - // Execute provided payment code - let payment_result = { - // payment_code_spec_1: init pay environment w/ gas limit == (max_payment_cost / - // gas_price) - let payment_gas_limit = match Gas::from_motes(max_payment_cost, deploy_item.gas_price) { - Some(gas) => gas, - None => { - return Ok(ExecutionResult::precondition_failure( - Error::GasConversionOverflow, - )) - } - }; - - // Create payment code module from bytes - // validation_spec_1: valid wasm bytes - let phase = Phase::Payment; - - let payment_stack = RuntimeStack::from_account_hash( - deploy_item.address, - self.config.max_runtime_call_stack_height() as usize, - ); - - // payment_code_spec_2: execute payment code - let payment_access_rights = - entity.extract_access_rights(entity_hash, &entity_named_keys); - - let mut payment_named_keys = entity_named_keys.clone(); - - let payment_args = payment.args().clone(); - - if payment.is_standard_payment(phase) { - // Todo potentially could be moved to Executor::Exec - match executor.exec_standard_payment( - payment_args, - &entity, - entity_kind, - authorization_keys.clone(), - account_hash, - blocktime, - deploy_hash, - payment_gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - self.config.max_runtime_call_stack_height() as usize, - ) { - Ok(payment_result) => payment_result, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - } - } else { - let payment_execution_kind = match ExecutionKind::new( - Rc::clone(&tracking_copy), - &entity_named_keys, - payment, - &protocol_version, - phase, - ) { - Ok(execution_kind) => execution_kind, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - }; - executor.exec( - payment_execution_kind, - payment_args, - entity_hash, - &entity, - entity_kind, - &mut payment_named_keys, - payment_access_rights, - authorization_keys.clone(), - account_hash, - blocktime, - deploy_hash, - payment_gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - phase, - payment_stack, - ) - } - }; - payment_result.log_execution_result("payment result"); - - // If provided wasm file was malformed, we should charge. - if payment_result.should_charge_for_errors_in_wasm() { - let error = payment_result - .as_error() - .cloned() - .unwrap_or(Error::InsufficientPayment); - - return match ExecutionResult::new_payment_code_error( - error, - max_payment_cost, - account_main_purse_balance, - payment_result.cost(), - entity_main_purse_key, - rewards_target_purse_balance_key, - ) { - Ok(execution_result) => Ok(execution_result), - Err(error) => Ok(ExecutionResult::precondition_failure(error)), - }; - } - - let payment_result_cost = payment_result.cost(); - // payment_code_spec_3: fork based upon payment purse balance and cost of - // payment code execution - - // Get handle payment system contract details - // payment_code_spec_6: system contract validity - let system_contract_registry = tracking_copy.borrow_mut().get_system_entity_registry()?; - - let handle_payment_contract_hash = system_contract_registry - .get(HANDLE_PAYMENT) - .ok_or_else(|| { - error!("Missing system handle payment contract hash"); - Error::MissingSystemContractHash(HANDLE_PAYMENT.to_string()) - })?; - - let handle_payment_addr = - EntityAddr::new_system_entity_addr(handle_payment_contract_hash.value()); - - let handle_payment_named_keys = match tracking_copy + let mut named_keys = match tc .borrow_mut() - .get_named_keys(handle_payment_addr) + .get_named_keys(entity.entity_addr(entity_hash)) .map_err(Into::into) { Ok(named_keys) => named_keys, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error)); - } - }; - - // Get payment purse Key from handle payment contract - // payment_code_spec_6: system contract validity - let payment_purse_key: Key = - match handle_payment_named_keys.get(handle_payment::PAYMENT_PURSE_KEY) { - Some(key) => *key, - None => return Ok(ExecutionResult::precondition_failure(Error::Deploy)), - }; - let purse_balance_key = match tracking_copy - .borrow_mut() - .get_purse_balance_key(payment_purse_key) - { - Ok(key) => key, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error.into())); - } - }; - let payment_purse_balance: Motes = { - match tracking_copy - .borrow_mut() - .get_purse_balance(purse_balance_key) - { - Ok(balance) => balance, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error.into())); - } + Err(tce) => { + return WasmV1Result::precondition_failure(gas_limit, Error::TrackingCopy(tce)) } }; - - if let Some(forced_transfer) = - payment_result.check_forced_transfer(payment_purse_balance, deploy_item.gas_price) - { - // Get rewards purse balance key - // payment_code_spec_6: system contract validity - let error = match forced_transfer { - ForcedTransferResult::InsufficientPayment => Error::InsufficientPayment, - ForcedTransferResult::GasConversionOverflow => Error::GasConversionOverflow, - ForcedTransferResult::PaymentFailure => payment_result - .take_error() - .unwrap_or(Error::InsufficientPayment), - }; - - let gas_cost = match Gas::from_motes(max_payment_cost, deploy_item.gas_price) { - Some(gas) => gas, - None => { - return Ok(ExecutionResult::precondition_failure( - Error::GasConversionOverflow, - )) - } - }; - - return match ExecutionResult::new_payment_code_error( - error, - max_payment_cost, - account_main_purse_balance, - gas_cost, - entity_main_purse_key, - rewards_target_purse_balance_key, - ) { - Ok(execution_result) => Ok(execution_result), - Err(error) => Ok(ExecutionResult::precondition_failure(error)), - }; - }; - - // Transfer the contents of the rewards purse to block proposer - execution_result_builder.set_payment_execution_result(payment_result); - - // Begin session logic handling - let post_payment_tracking_copy = tracking_copy.borrow(); - let session_tracking_copy = Rc::new(RefCell::new(post_payment_tracking_copy.fork())); - - let session_stack = RuntimeStack::from_account_hash( - deploy_item.address, - self.config.max_runtime_call_stack_height() as usize, - ); - - let mut session_named_keys = entity_named_keys.clone(); - - let session_access_rights = entity.extract_access_rights(entity_hash, &entity_named_keys); - - let mut session_result = { - // payment_code_spec_3_b_i: if (balance of handle payment pay purse) >= (gas spent - // during payment code execution) * gas_price, yes session - // session_code_spec_1: gas limit = ((balance of handle payment payment purse) / - // gas_price) - // - (gas spent during payment execution) - let session_gas_limit: Gas = - match Gas::from_motes(payment_purse_balance, deploy_item.gas_price) - .and_then(|gas| gas.checked_sub(payment_result_cost)) - { - Some(gas) => gas, - None => { - return Ok(ExecutionResult::precondition_failure( - Error::GasConversionOverflow, - )) - } - }; - - executor.exec( - session_execution_kind, - session_args, - entity_hash, - &entity, - entity_kind, - &mut session_named_keys, - session_access_rights, - authorization_keys.clone(), - account_hash, - blocktime, - deploy_hash, - session_gas_limit, - protocol_version, - Rc::clone(&session_tracking_copy), - Phase::Session, - session_stack, - ) - }; - session_result.log_execution_result("session result"); - - // Create + persist deploy info. - { - let transfers = session_result.transfers(); - let cost = payment_result_cost.value() + session_result.cost().value(); - let deploy_info = DeployInfo::new( - deploy_hash, - transfers, + let execution_kind = match ExecutionKind::new( + &mut *tc.borrow_mut(), + &named_keys, + &executable_item, + entry_point, + protocol_version, + ) { + Ok(execution_kind) => execution_kind, + Err(ese) => return WasmV1Result::precondition_failure(gas_limit, ese), + }; + let access_rights = entity.extract_access_rights(entity_hash, &named_keys); + Executor::new(self.config().clone()).exec( + execution_kind, + args, + entity_hash, + &entity, + &mut named_keys, + access_rights, + authorization_keys, + account_hash, + block_time, + transaction_hash, + gas_limit, + protocol_version, + Rc::clone(&tc), + phase, + RuntimeStack::from_account_hash( account_hash, - entity.main_purse(), - cost, - ); - session_tracking_copy.borrow_mut().write( - Key::DeployInfo(deploy_hash), - StoredValue::DeployInfo(deploy_info), - ); - } - - // Session execution was zero cost or provided wasm was malformed. - // Check if the payment purse can cover the minimum floor for session execution. - if (session_result.cost().is_zero() && payment_purse_balance < max_payment_cost) - || session_result.should_charge_for_errors_in_wasm() - { - // When session code structure is valid but still has 0 cost we should propagate the - // error. - let error = session_result - .as_error() - .cloned() - .unwrap_or(Error::InsufficientPayment); - - return match ExecutionResult::new_payment_code_error( - error, - max_payment_cost, - account_main_purse_balance, - session_result.cost(), - entity_main_purse_key, - rewards_target_purse_balance_key, - ) { - Ok(execution_result) => Ok(execution_result), - Err(error) => Ok(ExecutionResult::precondition_failure(error)), - }; - } - - let post_session_rc = if session_result.is_failure() { - // If session code fails we do not include its effects, - // so we start again from the post-payment state. - Rc::new(RefCell::new(post_payment_tracking_copy.fork())) - } else { - session_result = session_result.with_effects(session_tracking_copy.borrow().effects()); - session_tracking_copy - }; - - // NOTE: session_code_spec_3: (do not include session execution effects in - // results) is enforced in execution_result_builder.build() - execution_result_builder.set_session_execution_result(session_result); - - // payment_code_spec_5: run finalize process - let finalize_result: ExecutionResult = { - let post_session_tc = post_session_rc.borrow(); - let finalization_tc = Rc::new(RefCell::new(post_session_tc.fork())); - - let handle_payment_args = { - //((gas spent during payment code execution) + (gas spent during session code execution)) * gas_price - let finalize_cost_motes = match Motes::from_gas( - execution_result_builder.total_cost(), - deploy_item.gas_price, - ) { - Some(motes) => motes, - None => { - return Ok(ExecutionResult::precondition_failure( - Error::GasConversionOverflow, - )) - } - }; - - let maybe_runtime_args = RuntimeArgs::try_new(|args| { - args.insert(handle_payment::ARG_AMOUNT, finalize_cost_motes.value())?; - args.insert(handle_payment::ARG_ACCOUNT, account_hash)?; - args.insert(handle_payment::ARG_TARGET, rewards_target_purse)?; - Ok(()) - }); - match maybe_runtime_args { - Ok(runtime_args) => runtime_args, - Err(error) => { - let exec_error = ExecError::from(error); - return Ok(ExecutionResult::precondition_failure(exec_error.into())); - } - } - }; - - // The Handle Payment keys may have changed because of effects during payment and/or - // session, so we need to look them up again from the tracking copy - let system_contract_registry = - finalization_tc.borrow_mut().get_system_entity_registry()?; - - let handle_payment_contract_hash = system_contract_registry - .get(HANDLE_PAYMENT) - .ok_or_else(|| { - error!("Missing system handle payment contract hash"); - Error::MissingSystemContractHash(HANDLE_PAYMENT.to_string()) - })?; - - let handle_payment_contract = match finalization_tc - .borrow_mut() - .get_addressable_entity_by_hash(*handle_payment_contract_hash) - { - Ok(info) => info, - Err(error) => return Ok(ExecutionResult::precondition_failure(error.into())), - }; - - let handle_payment_addr = - EntityAddr::new_system_entity_addr(handle_payment_contract_hash.value()); - - let handle_payment_named_keys = match finalization_tc - .borrow_mut() - .get_named_keys(handle_payment_addr) - { - Ok(named_keys) => named_keys, - Err(error) => return Ok(ExecutionResult::precondition_failure(error.into())), - }; - - let mut handle_payment_access_rights = handle_payment_contract - .extract_access_rights(*handle_payment_contract_hash, &handle_payment_named_keys); - handle_payment_access_rights.extend(&[payment_purse_uref, rewards_target_purse]); - - let gas_limit = Gas::new(U512::MAX); - - let handle_payment_stack = RuntimeStack::new_system_call_stack( self.config.max_runtime_call_stack_height() as usize, - ); - let system_account_hash = PublicKey::System.to_account_hash(); - - let (_ret, finalize_result): (Option<()>, ExecutionResult) = executor - .call_system_contract( - DirectSystemContractCall::FinalizePayment, - handle_payment_args, - &system_addressable_entity, - EntityKind::Account(system_account_hash), - authorization_keys, - system_account_hash, - blocktime, - deploy_hash, - gas_limit, - protocol_version, - finalization_tc, - Phase::FinalizePayment, - handle_payment_stack, - U512::zero(), - ); - - finalize_result - }; - - execution_result_builder.set_finalize_execution_result(finalize_result); - - // We panic here to indicate that the builder was not used properly. - let ret = execution_result_builder - .build() - .expect("ExecutionResultBuilder not initialized properly"); - - // NOTE: payment_code_spec_5_a is enforced in execution_result_builder.build() - // payment_code_spec_6: return properly combined set of transforms and - // appropriate error - Ok(ret) + ), + ) } } diff --git a/execution_engine/src/engine_state/wasm_v1.rs b/execution_engine/src/engine_state/wasm_v1.rs new file mode 100644 index 0000000000..a98f24dbcc --- /dev/null +++ b/execution_engine/src/engine_state/wasm_v1.rs @@ -0,0 +1,652 @@ +use std::{collections::BTreeSet, convert::TryFrom}; + +use serde::Serialize; +use thiserror::Error; + +use casper_storage::data_access_layer::TransferResult; +use casper_types::{ + account::AccountHash, bytesrepr::Bytes, contract_messages::Messages, execution::Effects, + runtime_args, system::mint::ARG_AMOUNT, BlockTime, DeployHash, Digest, ExecutableDeployItem, + Gas, InitiatorAddr, Phase, PricingMode, RuntimeArgs, Transaction, TransactionEntryPoint, + TransactionHash, TransactionInvocationTarget, TransactionSessionKind, TransactionTarget, + TransactionV1, Transfer, U512, +}; + +use crate::engine_state::{DeployItem, Error as EngineError}; + +const DEFAULT_ENTRY_POINT: &str = "call"; + +/// Error returned if constructing a new [`WasmV1Request`] fails. +#[derive(Clone, Eq, PartialEq, Error, Serialize, Debug)] +pub enum InvalidRequest { + /// Missing custom payment. + #[error("custom payment not found for {0}")] + CustomPaymentNotFound(TransactionHash), + /// Unexpected variant. + #[error("unexpected variant for {0} attempting {1}")] + UnexpectedVariant(TransactionHash, String), + /// Unsupported mode. + #[error("unsupported mode for {0} attempting {1}")] + UnsupportedMode(TransactionHash, String), + /// Invalid entry point. + #[error("invalid entry point for {0} attempting {1}")] + InvalidEntryPoint(TransactionHash, String), + /// Invalid target. + #[error("invalid target for {0} attempting {1}")] + InvalidTarget(TransactionHash, String), +} + +/// The item to be executed. +#[derive(Debug, Clone)] +pub enum ExecutableItem { + /// Legacy deploy byte code. + LegacyDeploy(Bytes), + /// Payment byte code. + PaymentBytes(Bytes), + /// Session byte code. + SessionBytes { + /// The kind of session. + kind: TransactionSessionKind, + /// The compiled Wasm. + module_bytes: Bytes, + }, + /// An attempt to invoke a stored entity or package. + Invocation(TransactionInvocationTarget), +} + +/// A request to execute the given Wasm on the V1 runtime. +#[derive(Debug)] +pub struct WasmV1Request { + /// State root hash of the global state in which the transaction will be executed. + pub state_hash: Digest, + /// Block time represented as a unix timestamp. + pub block_time: BlockTime, + /// The hash identifying the transaction. + pub transaction_hash: TransactionHash, + /// The number of Motes per unit of Gas to be paid for execution. + pub gas_limit: Gas, + /// The transaction's initiator. + pub initiator_addr: InitiatorAddr, + /// The executable item. + pub executable_item: ExecutableItem, + /// The entry point to call when executing. + pub entry_point: String, + /// The runtime args. + pub args: RuntimeArgs, + /// The account hashes of the signers of the transaction. + pub authorization_keys: BTreeSet, + /// Execution phase. + pub phase: Phase, +} + +impl WasmV1Request { + pub(crate) fn new_from_executable_info( + state_hash: Digest, + block_time: BlockTime, + gas_limit: Gas, + transaction_hash: TransactionHash, + initiator_addr: InitiatorAddr, + authorization_keys: BTreeSet, + executable_info: impl Executable, + ) -> Self { + let executable_item = executable_info.item(); + Self { + state_hash, + block_time, + transaction_hash, + gas_limit, + initiator_addr, + authorization_keys, + executable_item, + entry_point: executable_info.entry_point().clone(), + args: executable_info.args().clone(), + phase: executable_info.phase(), + } + } + + /// Creates a new request from a transaction for use as the session code. + pub fn new_session( + state_hash: Digest, + block_time: BlockTime, + gas_limit: Gas, + transaction: &Transaction, + ) -> Result { + let info = match transaction { + Transaction::Deploy(deploy) => { + SessionInfo::try_from((deploy.session(), deploy.hash()))? + } + Transaction::V1(v1_txn) => SessionInfo::try_from(v1_txn)?, + }; + + let transaction_hash = transaction.hash(); + let initiator_addr = transaction.initiator_addr(); + let authorization_keys = transaction.signers(); + Ok(WasmV1Request::new_from_executable_info( + state_hash, + block_time, + gas_limit, + transaction_hash, + initiator_addr, + authorization_keys, + info, + )) + } + + /// Creates a new request from a transaction for use as custom payment. + pub fn new_custom_payment( + state_hash: Digest, + block_time: BlockTime, + gas_limit: Gas, + transaction: &Transaction, + ) -> Result { + let info = match transaction { + Transaction::Deploy(deploy) => { + PaymentInfo::try_from((deploy.payment(), deploy.hash()))? + } + Transaction::V1(v1_txn) => PaymentInfo::try_from(v1_txn)?, + }; + + let transaction_hash = transaction.hash(); + let initiator_addr = transaction.initiator_addr(); + let authorization_keys = transaction.signers(); + Ok(WasmV1Request::new_from_executable_info( + state_hash, + block_time, + gas_limit, + transaction_hash, + initiator_addr, + authorization_keys, + info, + )) + } + + /// Creates a new request from a deploy item for use as the session code. + pub fn new_session_from_deploy_item( + state_hash: Digest, + block_time: BlockTime, + gas_limit: Gas, + DeployItem { + ref address, + ref session, + ref authorization_keys, + ref deploy_hash, + .. + }: &DeployItem, + ) -> Result { + let info = SessionInfo::try_from((session, deploy_hash))?; + let transaction_hash = TransactionHash::Deploy(*deploy_hash); + let initiator_addr = InitiatorAddr::AccountHash(*address); + let authorization_keys = authorization_keys.clone(); + Ok(WasmV1Request::new_from_executable_info( + state_hash, + block_time, + gas_limit, + transaction_hash, + initiator_addr, + authorization_keys, + info, + )) + } + + /// Creates a new request from a deploy item for use as custom payment. + pub fn new_custom_payment_from_deploy_item( + state_hash: Digest, + block_time: BlockTime, + gas_limit: Gas, + DeployItem { + ref address, + ref payment, + ref authorization_keys, + ref deploy_hash, + .. + }: &DeployItem, + ) -> Result { + let info = PaymentInfo::try_from((payment, deploy_hash))?; + let transaction_hash = TransactionHash::Deploy(*deploy_hash); + let initiator_addr = InitiatorAddr::AccountHash(*address); + let authorization_keys = authorization_keys.clone(); + Ok(WasmV1Request::new_from_executable_info( + state_hash, + block_time, + gas_limit, + transaction_hash, + initiator_addr, + authorization_keys, + info, + )) + } +} + +/// Wasm v1 result. +#[derive(Clone, Debug)] +pub struct WasmV1Result { + /// List of transfers that happened during execution. + transfers: Vec, + /// Gas limit. + limit: Gas, + /// Gas consumed. + consumed: Gas, + /// Execution effects. + effects: Effects, + /// Messages emitted during execution. + messages: Messages, + /// Did the wasm execute successfully? + error: Option, +} + +impl WasmV1Result { + /// Creates a new instance. + pub fn new( + limit: Gas, + consumed: Gas, + effects: Effects, + transfers: Vec, + messages: Messages, + error: Option, + ) -> Self { + WasmV1Result { + limit, + consumed, + effects, + transfers, + messages, + error, + } + } + + /// Error, if any. + pub fn error(&self) -> Option<&EngineError> { + self.error.as_ref() + } + + /// List of transfers that happened during execution. + pub fn transfers(&self) -> &Vec { + &self.transfers + } + + /// Gas limit. + pub fn limit(&self) -> Gas { + self.limit + } + + /// Gas consumed. + pub fn consumed(&self) -> Gas { + self.consumed + } + + /// Execution effects. + pub fn effects(&self) -> &Effects { + &self.effects + } + + /// Messages emitted during execution. + pub fn messages(&self) -> &Messages { + &self.messages + } + + /// Root not found. + pub fn root_not_found(gas_limit: Gas, state_hash: Digest) -> Self { + WasmV1Result { + transfers: Vec::default(), + effects: Effects::new(), + messages: Vec::default(), + limit: gas_limit, + consumed: Gas::zero(), + error: Some(EngineError::RootNotFound(state_hash)), + } + } + + /// Precondition failure. + pub fn precondition_failure(gas_limit: Gas, error: EngineError) -> Self { + WasmV1Result { + transfers: Vec::default(), + effects: Effects::new(), + messages: Vec::default(), + limit: gas_limit, + consumed: Gas::zero(), + error: Some(error), + } + } + + /// Failed to transform transaction into an executable item. + pub fn invalid_executable_item(gas_limit: Gas, error: InvalidRequest) -> Self { + WasmV1Result { + transfers: Vec::default(), + effects: Effects::new(), + messages: Vec::default(), + limit: gas_limit, + consumed: Gas::zero(), + error: Some(EngineError::InvalidExecutableItem(error)), + } + } + + /// Returns `true` if this is a precondition failure. + /// + /// Precondition variant is further described as an execution failure which does not have any + /// effects, and has a gas cost of 0. + pub fn has_precondition_failure(&self) -> bool { + self.error.is_some() && self.consumed == Gas::zero() && self.effects.is_empty() + } + + /// Converts a transfer result to an execution result. + pub fn from_transfer_result(transfer_result: TransferResult, consumed: Gas) -> Option { + // NOTE: for native / wasmless operations limit and consumed are always equal, and + // we can get away with simplifying to one or the other here. + // this is NOT true of wasm based operations however. + match transfer_result { + TransferResult::RootNotFound => None, + TransferResult::Success { transfers, effects } => Some(WasmV1Result { + transfers, + limit: consumed, + consumed, + effects, + messages: Messages::default(), + error: None, + }), + TransferResult::Failure(te) => { + Some(WasmV1Result { + transfers: vec![], + limit: consumed, + consumed, + effects: Effects::default(), // currently not returning effects on failure + messages: Messages::default(), + error: Some(EngineError::Transfer(te)), + }) + } + } + } +} + +/// Helper struct to carry item, entry_point, and arg info for a `WasmV1Request`. +struct ExecutableInfo { + item: ExecutableItem, + entry_point: String, + args: RuntimeArgs, +} + +pub(crate) trait Executable { + fn item(&self) -> ExecutableItem; + fn entry_point(&self) -> &String; + fn args(&self) -> &RuntimeArgs; + fn phase(&self) -> Phase; +} + +/// New type for hanging session specific impl's off of. +struct SessionInfo(ExecutableInfo); + +impl Executable for SessionInfo { + fn item(&self) -> ExecutableItem { + self.0.item.clone() + } + + fn entry_point(&self) -> &String { + &self.0.entry_point + } + + fn args(&self) -> &RuntimeArgs { + &self.0.args + } + + fn phase(&self) -> Phase { + Phase::Session + } +} + +impl TryFrom<(&ExecutableDeployItem, &DeployHash)> for SessionInfo { + type Error = InvalidRequest; + + fn try_from( + (session_item, deploy_hash): (&ExecutableDeployItem, &DeployHash), + ) -> Result { + let transaction_hash = TransactionHash::Deploy(*deploy_hash); + let session: ExecutableItem; + let session_entry_point: String; + let session_args: RuntimeArgs; + match session_item { + ExecutableDeployItem::ModuleBytes { module_bytes, args } => { + session = ExecutableItem::LegacyDeploy(module_bytes.clone()); + session_entry_point = DEFAULT_ENTRY_POINT.to_string(); + session_args = args.clone(); + } + ExecutableDeployItem::StoredContractByHash { + hash, + entry_point, + args, + } => { + session = ExecutableItem::Invocation( + TransactionInvocationTarget::new_invocable_entity(*hash), + ); + session_entry_point = entry_point.clone(); + session_args = args.clone(); + } + ExecutableDeployItem::StoredContractByName { + name, + entry_point, + args, + } => { + session = ExecutableItem::Invocation( + TransactionInvocationTarget::new_invocable_entity_alias(name.clone()), + ); + session_entry_point = entry_point.clone(); + session_args = args.clone(); + } + ExecutableDeployItem::StoredVersionedContractByHash { + hash, + version, + entry_point, + args, + } => { + session = ExecutableItem::Invocation(TransactionInvocationTarget::new_package( + *hash, *version, + )); + session_entry_point = entry_point.clone(); + session_args = args.clone(); + } + ExecutableDeployItem::StoredVersionedContractByName { + name, + version, + entry_point, + args, + } => { + session = ExecutableItem::Invocation( + TransactionInvocationTarget::new_package_alias(name.clone(), *version), + ); + session_entry_point = entry_point.clone(); + session_args = args.clone(); + } + ExecutableDeployItem::Transfer { .. } => { + return Err(InvalidRequest::UnsupportedMode( + transaction_hash, + session_item.to_string(), + )); + } + } + + Ok(SessionInfo(ExecutableInfo { + item: session, + entry_point: session_entry_point, + args: session_args, + })) + } +} + +impl TryFrom<&TransactionV1> for SessionInfo { + type Error = InvalidRequest; + + fn try_from(v1_txn: &TransactionV1) -> Result { + let transaction_hash = TransactionHash::V1(*v1_txn.hash()); + let args = v1_txn.args().clone(); + let session = match v1_txn.target() { + TransactionTarget::Native => { + return Err(InvalidRequest::InvalidTarget( + transaction_hash, + v1_txn.target().to_string(), + )); + } + TransactionTarget::Stored { id, .. } => ExecutableItem::Invocation(id.clone()), + TransactionTarget::Session { + kind, module_bytes, .. + } => ExecutableItem::SessionBytes { + kind: *kind, + module_bytes: module_bytes.clone(), + }, + }; + + let TransactionEntryPoint::Custom(entry_point) = v1_txn.entry_point() else { + return Err(InvalidRequest::InvalidEntryPoint(transaction_hash, v1_txn.entry_point().to_string())); + }; + + Ok(SessionInfo(ExecutableInfo { + item: session, + entry_point: entry_point.clone(), + args, + })) + } +} + +/// New type for hanging payment specific impl's off of. +struct PaymentInfo(ExecutableInfo); + +impl Executable for PaymentInfo { + fn item(&self) -> ExecutableItem { + self.0.item.clone() + } + + fn entry_point(&self) -> &String { + &self.0.entry_point + } + + fn args(&self) -> &RuntimeArgs { + &self.0.args + } + + fn phase(&self) -> Phase { + Phase::Payment + } +} + +impl TryFrom<(&ExecutableDeployItem, &DeployHash)> for PaymentInfo { + type Error = InvalidRequest; + + fn try_from( + (payment_item, deploy_hash): (&ExecutableDeployItem, &DeployHash), + ) -> Result { + let transaction_hash = TransactionHash::Deploy(*deploy_hash); + match payment_item { + ExecutableDeployItem::ModuleBytes { module_bytes, args } => { + let payment = if module_bytes.is_empty() { + return Err(InvalidRequest::UnsupportedMode( + transaction_hash, + "standard payment is no longer handled by the execution engine".to_string(), + )); + } else { + ExecutableItem::PaymentBytes(module_bytes.clone()) + }; + Ok(PaymentInfo(ExecutableInfo { + item: payment, + entry_point: DEFAULT_ENTRY_POINT.to_string(), + args: args.clone(), + })) + } + ExecutableDeployItem::StoredContractByHash { + hash, + args, + entry_point, + } => Ok(PaymentInfo(ExecutableInfo { + item: ExecutableItem::Invocation(TransactionInvocationTarget::ByHash(hash.value())), + entry_point: entry_point.clone(), + args: args.clone(), + })), + ExecutableDeployItem::StoredContractByName { + name, + args, + entry_point, + } => Ok(PaymentInfo(ExecutableInfo { + item: ExecutableItem::Invocation(TransactionInvocationTarget::ByName(name.clone())), + entry_point: entry_point.clone(), + args: args.clone(), + })), + ExecutableDeployItem::StoredVersionedContractByHash { + args, + hash, + version, + entry_point, + } => Ok(PaymentInfo(ExecutableInfo { + item: ExecutableItem::Invocation(TransactionInvocationTarget::ByPackageHash { + addr: hash.value(), + version: *version, + }), + entry_point: entry_point.clone(), + args: args.clone(), + })), + ExecutableDeployItem::StoredVersionedContractByName { + name, + version, + args, + entry_point, + } => Ok(PaymentInfo(ExecutableInfo { + item: ExecutableItem::Invocation(TransactionInvocationTarget::ByPackageName { + name: name.clone(), + version: *version, + }), + entry_point: entry_point.clone(), + args: args.clone(), + })), + ExecutableDeployItem::Transfer { .. } => Err(InvalidRequest::UnexpectedVariant( + transaction_hash, + "payment item".to_string(), + )), + } + } +} + +impl TryFrom<&TransactionV1> for PaymentInfo { + type Error = InvalidRequest; + + fn try_from(v1_txn: &TransactionV1) -> Result { + let transaction_hash = TransactionHash::V1(*v1_txn.hash()); + let pricing_mode = v1_txn.pricing_mode(); + let payment_amount = match v1_txn.pricing_mode() { + PricingMode::Classic { + payment_amount, + standard_payment, + .. + } => { + if *standard_payment { + return Err(InvalidRequest::UnsupportedMode( + transaction_hash, + pricing_mode.to_string(), + )); + } + *payment_amount + } + PricingMode::Fixed { .. } | PricingMode::Reserved { .. } => { + return Err(InvalidRequest::UnsupportedMode( + transaction_hash, + pricing_mode.to_string(), + )); + } + }; + + let payment = match v1_txn.target() { + TransactionTarget::Session { module_bytes, .. } => { + ExecutableItem::PaymentBytes(module_bytes.clone()) + } + TransactionTarget::Native | TransactionTarget::Stored { .. } => { + return Err(InvalidRequest::InvalidTarget( + transaction_hash, + v1_txn.target().to_string(), + )); + } + }; + let args = runtime_args! { ARG_AMOUNT => U512::from(payment_amount)}; + let TransactionEntryPoint::Custom(entry_point) = v1_txn.entry_point().clone() else { + return Err(InvalidRequest::InvalidEntryPoint(transaction_hash, v1_txn.entry_point().to_string())); + }; + Ok(PaymentInfo(ExecutableInfo { + item: payment, + entry_point, + args, + })) + } +} diff --git a/execution_engine/src/execution/error.rs b/execution_engine/src/execution/error.rs index 7dad976f30..c76a2ef64e 100644 --- a/execution_engine/src/execution/error.rs +++ b/execution_engine/src/execution/error.rs @@ -5,9 +5,7 @@ use thiserror::Error; use casper_storage::{global_state, tracking_copy::TrackingCopyError}; use casper_types::{ - addressable_entity::{ - AddKeyFailure, EntityKind, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure, - }, + addressable_entity::{AddKeyFailure, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure}, bytesrepr, execution::TransformError, system, AccessRights, AddressableEntityHash, ApiError, ByteCodeHash, CLType, CLValueError, @@ -54,9 +52,6 @@ pub enum Error { /// Forged reference error. #[error("Forged reference: {}", _0)] ForgedReference(URef), - /// Unable to find a [`URef`]. - #[error("URef not found: {}", _0)] - URefNotFound(URef), /// Unable to find a function. #[error("Function not found: {}", _0)] FunctionNotFound(String), @@ -99,9 +94,6 @@ pub enum Error { /// Host buffer expected a value to be present. #[error("Expected return value")] ExpectedReturnValue, - /// Host buffer was not expected to contain a value. - #[error("Unexpected return value")] - UnexpectedReturnValue, /// Error calling a host function in a wrong context. #[error("Invalid context")] InvalidContext, @@ -116,11 +108,8 @@ pub enum Error { /// Error converting a CLValue. #[error("{0}")] CLValue(CLValueError), - /// Unable to access host buffer. - #[error("Host buffer is empty")] - HostBufferEmpty, /// WASM bytes contains an unsupported "start" section. - #[error("Unsupported WASM start")] + #[error("Unsupported Wasm start")] UnsupportedWasmStart, /// Contract package has no active contract versions. #[error("No active contract versions for contract package")] @@ -138,23 +127,17 @@ pub enum Error { #[error("No such method: {}", _0)] NoSuchMethod(String), /// Contract does - #[error("Error calling an abstract entry point: {}", _0)] + #[error("Error calling a template entry point: {}", _0)] TemplateMethod(String), /// Error processing WASM bytes. #[error("Wasm preprocessing error: {}", _0)] WasmPreprocessing(PreprocessingError), - /// Unable to convert a [`Key`] into an [`URef`]. - #[error("Key is not a URef: {}", _0)] - KeyIsNotAURef(Key), /// Unexpected variant of a stored value. #[error("Unexpected variant of a stored value")] UnexpectedStoredValueVariant, /// Error upgrading a locked contract package. #[error("A locked contract cannot be upgraded")] LockedEntity(PackageHash), - /// Unable to find a contract package by a specified hash address. - #[error("Invalid package: {}", _0)] - InvalidPackage(PackageHash), /// Unable to find a contract by a specified hash address. #[error("Invalid contract: {}", _0)] InvalidEntity(AddressableEntityHash), @@ -170,18 +153,12 @@ pub enum Error { /// Error writing a dictionary item key which exceeded maximum allowed length. #[error("Dictionary item key exceeded maximum length")] DictionaryItemKeyExceedsLength, - /// Missing system contract registry. - #[error("Missing system contract registry")] - MissingSystemContractRegistry, /// Missing system contract hash. #[error("Missing system contract hash: {0}")] MissingSystemContractHash(String), /// An attempt to push to the runtime stack which is already at the maximum height. #[error("Runtime stack overflow")] RuntimeStackOverflow, - /// An attempt to write a value to global state where its serialized size is too large. - #[error("Value too large")] - ValueTooLarge, /// The runtime stack is `None`. #[error("Runtime stack missing")] MissingRuntimeStack, @@ -194,9 +171,6 @@ pub enum Error { /// Invalid key #[error("Invalid key {0}")] UnexpectedKeyVariant(Key), - /// Invalid AddressableEntity kind. - #[error("Invalid entity kind: {0}")] - InvalidEntityKind(EntityKind), /// Failed to transfer tokens on a private chain. #[error("Failed to transfer with unrestricted transfers disabled")] DisabledUnrestrictedTransfers, diff --git a/execution_engine/src/execution/executor.rs b/execution_engine/src/execution/executor.rs index d845832dbd..53515d4713 100644 --- a/execution_engine/src/execution/executor.rs +++ b/execution_engine/src/execution/executor.rs @@ -1,28 +1,21 @@ -use std::{cell::RefCell, collections::BTreeSet, convert::TryFrom, rc::Rc}; +use std::{cell::RefCell, collections::BTreeSet, rc::Rc}; use casper_storage::{ global_state::{error::Error as GlobalStateError, state::StateReader}, - system::transfer::TransferArgs, - tracking_copy::{TrackingCopy, TrackingCopyEntityExt, TrackingCopyExt}, + tracking_copy::TrackingCopy, AddressGenerator, }; use casper_types::{ - account::AccountHash, - addressable_entity::{EntityKind, NamedKeys}, - bytesrepr::FromBytes, - system::{handle_payment, mint, HANDLE_PAYMENT, MINT}, - AddressableEntity, AddressableEntityHash, ApiError, BlockTime, CLTyped, ContextAccessRights, - DeployHash, EntityAddr, EntryPointType, Gas, Key, Phase, ProtocolVersion, RuntimeArgs, - StoredValue, Tagged, URef, U512, + account::AccountHash, addressable_entity::NamedKeys, execution::Effects, AddressableEntity, + AddressableEntityHash, BlockTime, ContextAccessRights, EntryPointType, Gas, Key, Phase, + ProtocolVersion, RuntimeArgs, StoredValue, Tagged, TransactionHash, U512, }; use crate::{ - engine_state::{ - execution_kind::ExecutionKind, EngineConfig, Error as EngineStateError, ExecutionResult, - }, + engine_state::{execution_kind::ExecutionKind, EngineConfig, WasmV1Result}, execution::ExecError, runtime::{Runtime, RuntimeStack}, - runtime_context::RuntimeContext, + runtime_context::{CallingAddContractVersion, RuntimeContext}, }; const ARG_AMOUNT: &str = "amount"; @@ -55,35 +48,51 @@ impl Executor { args: RuntimeArgs, entity_hash: AddressableEntityHash, entity: &AddressableEntity, - entity_kind: EntityKind, named_keys: &mut NamedKeys, access_rights: ContextAccessRights, authorization_keys: BTreeSet, account_hash: AccountHash, blocktime: BlockTime, - deploy_hash: DeployHash, + txn_hash: TransactionHash, gas_limit: Gas, protocol_version: ProtocolVersion, tracking_copy: Rc>>, phase: Phase, stack: RuntimeStack, - ) -> ExecutionResult + ) -> WasmV1Result where R: StateReader, { let spending_limit: U512 = match try_get_amount(&args) { Ok(spending_limit) => spending_limit, Err(error) => { - return ExecutionResult::precondition_failure(error.into()); + return WasmV1Result::new( + gas_limit, + Gas::zero(), + Effects::default(), + Vec::default(), + Vec::default(), + Some(error.into()), + ); } }; let address_generator = { - let generator = AddressGenerator::new(deploy_hash.as_ref(), phase); + let generator = AddressGenerator::new(txn_hash.as_ref(), phase); Rc::new(RefCell::new(generator)) }; - let entity_key = Key::addressable_entity_key(entity_kind.tag(), entity_hash); + let entity_key = Key::addressable_entity_key(entity.kind().tag(), entity_hash); + + let calling_add_contract_version = match execution_kind { + ExecutionKind::Installer(_) + | ExecutionKind::Upgrader(_) + | ExecutionKind::Stored { .. } + | ExecutionKind::Deploy(_) => CallingAddContractVersion::Allowed, + ExecutionKind::Standard(_) | ExecutionKind::Isolated(_) => { + CallingAddContractVersion::Forbidden + } + }; let context = self.create_runtime_context( named_keys, @@ -91,188 +100,54 @@ impl Executor { entity_key, authorization_keys, access_rights, - entity_kind, account_hash, address_generator, tracking_copy, blocktime, protocol_version, - deploy_hash, + txn_hash, phase, args.clone(), gas_limit, spending_limit, - EntryPointType::Session, + EntryPointType::Caller, + calling_add_contract_version, ); let mut runtime = Runtime::new(context); let result = match execution_kind { - ExecutionKind::Module(module_bytes) => { - runtime.execute_module_bytes(&module_bytes, stack) + ExecutionKind::Standard(module_bytes) + | ExecutionKind::Installer(module_bytes) + | ExecutionKind::Upgrader(module_bytes) + | ExecutionKind::Isolated(module_bytes) + | ExecutionKind::Deploy(module_bytes) => { + runtime.execute_module_bytes(module_bytes, stack) } - ExecutionKind::Contract { - entity_hash: contract_hash, - entry_point_name, + ExecutionKind::Stored { + entity_hash, + entry_point, } => { // These args are passed through here as they are required to construct the new // `Runtime` during the contract's execution (i.e. inside // `Runtime::execute_contract`). - runtime.call_contract_with_stack(contract_hash, &entry_point_name, args, stack) - } - }; - - match result { - Ok(_) => ExecutionResult::Success { - effects: runtime.context().effects(), - transfers: runtime.context().transfers().to_owned(), - cost: runtime.context().gas_counter(), - messages: runtime.context().messages(), - }, - Err(error) => ExecutionResult::Failure { - error: error.into(), - effects: runtime.context().effects(), - transfers: runtime.context().transfers().to_owned(), - cost: runtime.context().gas_counter(), - messages: runtime.context().messages(), - }, - } - } - - /// Handles necessary address resolution and orchestration to securely call a system contract - /// using the runtime. - #[allow(clippy::too_many_arguments)] - pub(crate) fn call_system_contract( - &self, - direct_system_contract_call: DirectSystemContractCall, - runtime_args: RuntimeArgs, - entity: &AddressableEntity, - entity_kind: EntityKind, - authorization_keys: BTreeSet, - account_hash: AccountHash, - blocktime: BlockTime, - deploy_hash: DeployHash, - gas_limit: Gas, - protocol_version: ProtocolVersion, - tracking_copy: Rc>>, - phase: Phase, - stack: RuntimeStack, - remaining_spending_limit: U512, - ) -> (Option, ExecutionResult) - where - R: StateReader, - T: FromBytes + CLTyped, - { - let address_generator = { - let generator = AddressGenerator::new(deploy_hash.as_ref(), phase); - Rc::new(RefCell::new(generator)) - }; - - // Today lack of existence of the system contract registry and lack of entry - // for the minimum defined system contracts (mint, auction, handle_payment) - // should cause the EE to panic. Do not remove the panics. - let system_contract_registry = tracking_copy - .borrow_mut() - .get_system_entity_registry() - .unwrap_or_else(|error| panic!("Could not retrieve system contracts: {:?}", error)); - - // Snapshot of effects before execution, so in case of error only nonce update - // can be returned. - let effects = tracking_copy.borrow().effects(); - let messages = tracking_copy.borrow().messages(); - - let entry_point_name = direct_system_contract_call.entry_point_name(); - - let entity_hash = match direct_system_contract_call { - DirectSystemContractCall::Transfer => { - let mint_hash = system_contract_registry - .get(MINT) - .expect("should have mint hash"); - *mint_hash - } - DirectSystemContractCall::FinalizePayment - | DirectSystemContractCall::GetPaymentPurse => { - let handle_payment_hash = system_contract_registry - .get(HANDLE_PAYMENT) - .expect("should have handle payment"); - *handle_payment_hash + runtime.call_contract_with_stack(entity_hash, &entry_point, args, stack) } }; - let contract = match tracking_copy - .borrow_mut() - .get_addressable_entity_by_hash(entity_hash) - { - Ok(contract) => contract, - Err(error) => return (None, ExecutionResult::precondition_failure(error.into())), + let err = match result { + Ok(_) => None, + Err(error) => Some(error.into()), }; - let entity_addr = EntityAddr::new_with_tag(entity_kind, entity_hash.value()); - - let mut named_keys = match tracking_copy.borrow_mut().get_named_keys(entity_addr) { - Ok(named_key) => named_key, - Err(error) => return (None, ExecutionResult::precondition_failure(error.into())), - }; - - let access_rights = contract.extract_access_rights(entity_hash, &named_keys); - let entity_key = entity_addr.into(); - let runtime_context = self.create_runtime_context( - &mut named_keys, - entity, - entity_key, - authorization_keys, - access_rights, - entity_kind, - account_hash, - address_generator, - tracking_copy, - blocktime, - protocol_version, - deploy_hash, - phase, - runtime_args.clone(), + return WasmV1Result::new( gas_limit, - remaining_spending_limit, - EntryPointType::AddressableEntity, + runtime.context().gas_counter(), + runtime.context().effects(), + runtime.context().transfers().to_owned(), + runtime.context().messages(), + err, ); - - let mut runtime = Runtime::new(runtime_context); - - // DO NOT alter this logic to call a system contract directly (such as via mint_internal, - // etc). Doing so would bypass necessary context based security checks in some use cases. It - // is intentional to use the runtime machinery for this interaction with the system - // contracts, to force all such security checks for usage via the executor into a single - // execution path. - let result = - runtime.call_contract_with_stack(entity_hash, entry_point_name, runtime_args, stack); - - match result { - Ok(value) => match value.into_t() { - Ok(ret) => ExecutionResult::Success { - effects: runtime.context().effects(), - transfers: runtime.context().transfers().to_owned(), - cost: runtime.context().gas_counter(), - messages: runtime.context().messages(), - } - .take_with_ret(ret), - Err(error) => ExecutionResult::Failure { - effects, - error: ExecError::CLValue(error).into(), - transfers: runtime.context().transfers().to_owned(), - cost: runtime.context().gas_counter(), - messages, - } - .take_without_ret(), - }, - Err(error) => ExecutionResult::Failure { - effects, - error: error.into(), - transfers: runtime.context().transfers().to_owned(), - cost: runtime.context().gas_counter(), - messages, - } - .take_without_ret(), - } } /// Creates new runtime context. @@ -284,18 +159,18 @@ impl Executor { entity_key: Key, authorization_keys: BTreeSet, access_rights: ContextAccessRights, - entity_kind: EntityKind, account_hash: AccountHash, address_generator: Rc>, tracking_copy: Rc>>, blocktime: BlockTime, protocol_version: ProtocolVersion, - deploy_hash: DeployHash, + txn_hash: TransactionHash, phase: Phase, runtime_args: RuntimeArgs, gas_limit: Gas, remaining_spending_limit: U512, entry_point_type: EntryPointType, + calling_add_contract_version: CallingAddContractVersion, ) -> RuntimeContext<'a, R> where R: StateReader, @@ -309,14 +184,13 @@ impl Executor { entity_key, authorization_keys, access_rights, - entity_kind, account_hash, address_generator, tracking_copy, self.config.clone(), blocktime, protocol_version, - deploy_hash, + txn_hash, phase, runtime_args, gas_limit, @@ -324,205 +198,7 @@ impl Executor { transfers, remaining_spending_limit, entry_point_type, + calling_add_contract_version, ) } - - /// Executes standard payment code natively. - #[allow(clippy::too_many_arguments)] - pub(crate) fn exec_standard_payment( - &self, - payment_args: RuntimeArgs, - entity: &AddressableEntity, - entity_kind: EntityKind, - authorization_keys: BTreeSet, - account_hash: AccountHash, - blocktime: BlockTime, - deploy_hash: DeployHash, - payment_gas_limit: Gas, - protocol_version: ProtocolVersion, - tracking_copy: Rc>>, - max_stack_height: usize, - ) -> Result - where - R: StateReader, - R::Error: Into, - { - let payment_amount: U512 = match try_get_amount(&payment_args) { - Ok(payment_amount) => payment_amount, - Err(error) => { - return Ok(ExecutionResult::precondition_failure(error.into())); - } - }; - - let get_payment_purse_stack = RuntimeStack::new_system_call_stack(max_stack_height); - - let (maybe_purse, get_payment_result) = self.get_payment_purse( - entity, - entity_kind, - authorization_keys.clone(), - account_hash, - blocktime, - deploy_hash, - payment_gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - get_payment_purse_stack, - ); - - if get_payment_result.as_error().is_some() { - return Ok(get_payment_result); - } - - let payment_purse = match maybe_purse { - Some(payment_purse) => payment_purse, - None => return Err(EngineStateError::reverter(ApiError::HandlePayment(12))), - }; - - let runtime_args = { - let transfer_args = TransferArgs::new( - None, - entity.main_purse(), - payment_purse, - payment_amount, - None, - ); - - match RuntimeArgs::try_from(transfer_args) { - Ok(runtime_args) => runtime_args, - Err(error) => { - return Ok(ExecutionResult::precondition_failure( - ExecError::CLValue(error).into(), - )) - } - } - }; - - let transfer_stack = RuntimeStack::new_system_call_stack(max_stack_height); - - let (transfer_result, payment_result) = self.invoke_mint_to_transfer( - runtime_args, - entity, - entity_kind, - authorization_keys, - account_hash, - blocktime, - deploy_hash, - payment_gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - transfer_stack, - payment_amount, - ); - - if payment_result.as_error().is_some() { - return Ok(payment_result); - } - - let transfer_result = match transfer_result { - Some(Ok(())) => Ok(()), - Some(Err(mint_error)) => match mint::Error::try_from(mint_error) { - Ok(mint_error) => Err(EngineStateError::reverter(mint_error)), - Err(_) => Err(EngineStateError::reverter(ApiError::Transfer)), - }, - None => Err(EngineStateError::reverter(ApiError::Transfer)), - }; - - transfer_result?; - - Ok(payment_result) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn get_payment_purse( - &self, - entity: &AddressableEntity, - entity_kind: EntityKind, - authorization_keys: BTreeSet, - account_hash: AccountHash, - blocktime: BlockTime, - deploy_hash: DeployHash, - payment_gas_limit: Gas, - protocol_version: ProtocolVersion, - tracking_copy: Rc>>, - stack: RuntimeStack, - ) -> (Option, ExecutionResult) - where - R: StateReader, - R::Error: Into, - { - self.call_system_contract( - DirectSystemContractCall::GetPaymentPurse, - RuntimeArgs::new(), - entity, - entity_kind, - authorization_keys, - account_hash, - blocktime, - deploy_hash, - payment_gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - Phase::Payment, - stack, - U512::zero(), - ) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn invoke_mint_to_transfer( - &self, - runtime_args: RuntimeArgs, - entity: &AddressableEntity, - entity_kind: EntityKind, - authorization_keys: BTreeSet, - account_hash: AccountHash, - blocktime: BlockTime, - deploy_hash: DeployHash, - gas_limit: Gas, - protocol_version: ProtocolVersion, - tracking_copy: Rc>>, - stack: RuntimeStack, - spending_limit: U512, - ) -> (Option>, ExecutionResult) - where - R: StateReader, - R::Error: Into, - { - self.call_system_contract( - DirectSystemContractCall::Transfer, - runtime_args, - entity, - entity_kind, - authorization_keys, - account_hash, - blocktime, - deploy_hash, - gas_limit, - protocol_version, - Rc::clone(&tracking_copy), - Phase::Payment, - stack, - spending_limit, - ) - } -} - -/// Represents a variant of a system contract call. -pub(crate) enum DirectSystemContractCall { - /// Calls handle payment's `finalize` entry point. - FinalizePayment, - /// Calls mint's `transfer` entry point. - Transfer, - /// Calls handle payment's `get_payment_purse` entry point. - GetPaymentPurse, -} - -impl DirectSystemContractCall { - fn entry_point_name(&self) -> &str { - match self { - DirectSystemContractCall::FinalizePayment => handle_payment::METHOD_FINALIZE_PAYMENT, - DirectSystemContractCall::Transfer => mint::METHOD_TRANSFER, - DirectSystemContractCall::GetPaymentPurse => handle_payment::METHOD_GET_PAYMENT_PURSE, - } - } } diff --git a/execution_engine/src/execution/mod.rs b/execution_engine/src/execution/mod.rs index cf40e67f21..b4cf640369 100644 --- a/execution_engine/src/execution/mod.rs +++ b/execution_engine/src/execution/mod.rs @@ -4,4 +4,4 @@ mod error; mod executor; pub use self::error::Error as ExecError; -pub(crate) use self::executor::{DirectSystemContractCall, Executor}; +pub(crate) use self::executor::Executor; diff --git a/execution_engine/src/runtime/auction_internal.rs b/execution_engine/src/runtime/auction_internal.rs index e91d8a3dad..593876e602 100644 --- a/execution_engine/src/runtime/auction_internal.rs +++ b/execution_engine/src/runtime/auction_internal.rs @@ -16,7 +16,7 @@ use casper_types::{ auction::{BidAddr, BidKind, EraInfo, Error, UnbondingPurse}, mint, }, - CLTyped, CLValue, Key, KeyTag, PublicKey, RuntimeArgs, StoredValue, URef, U512, + CLTyped, CLValue, HoldsEpoch, Key, KeyTag, PublicKey, RuntimeArgs, StoredValue, URef, U512, }; use super::Runtime; @@ -213,7 +213,7 @@ where AccountHash::from_public_key(unbonding_purse.unbonder_public_key(), crypto::blake2b); let maybe_value = self .context - .read_gs_direct(&Key::Account(account_hash)) + .read_gs_unsafe(&Key::Account(account_hash)) .map_err(|exec_error| { error!("MintProvider::unbond: {:?}", exec_error); >::from(exec_error).unwrap_or(Error::Storage) @@ -230,7 +230,7 @@ where let maybe_value = self .context - .read_gs_direct(&contract_key) + .read_gs_unsafe(&contract_key) .map_err(|exec_error| { error!("MintProvider::unbond: {:?}", exec_error); >::from(exec_error).unwrap_or(Error::Storage) @@ -244,6 +244,7 @@ where contract.main_purse(), *unbonding_purse.amount(), None, + HoldsEpoch::NOT_APPLICABLE, ) .map_err(|_| Error::Transfer)? .map_err(|_| Error::Transfer)?; @@ -264,6 +265,7 @@ where target: URef, amount: U512, id: Option, + _holds_epoch: HoldsEpoch, ) -> Result, Error> { if !(self.context.entity().main_purse().addr() == source.addr() || self.context.get_caller() == PublicKey::System.to_account_hash()) @@ -340,8 +342,12 @@ where }) } - fn get_balance(&mut self, purse: URef) -> Result, Error> { - Runtime::get_balance(self, purse) + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { + Runtime::available_balance(self, purse, holds_epoch) .map_err(|exec_error| >::from(exec_error).unwrap_or(Error::GetBalance)) } diff --git a/execution_engine/src/runtime/externals.rs b/execution_engine/src/runtime/externals.rs index 648b9ff0f5..1a3e45d846 100644 --- a/execution_engine/src/runtime/externals.rs +++ b/execution_engine/src/runtime/externals.rs @@ -13,11 +13,10 @@ use casper_types::{ bytesrepr::{self, ToBytes}, contract_messages::MessageTopicOperation, crypto, - package::PackageStatus, system::auction::EraInfo, AddressableEntityHash, ApiError, EntityVersion, EraId, Gas, Group, HostFunction, - HostFunctionCost, Key, PackageHash, StoredValue, URef, DEFAULT_HOST_FUNCTION_NEW_DICTIONARY, - U512, UREF_SERIALIZED_LENGTH, + HostFunctionCost, Key, PackageHash, PackageStatus, StoredValue, URef, + DEFAULT_HOST_FUNCTION_NEW_DICTIONARY, U512, UREF_SERIALIZED_LENGTH, }; use super::{args::Args, ExecError, Runtime}; @@ -195,7 +194,7 @@ where let (gas_arg,): (u32,) = Args::parse(args)?; // Gas is special cased internal host function and for accounting purposes it isn't // represented in protocol data. - self.gas(Gas::new(gas_arg.into()))?; + self.gas(Gas::new(gas_arg))?; Ok(None) } diff --git a/execution_engine/src/runtime/handle_payment_internal.rs b/execution_engine/src/runtime/handle_payment_internal.rs index 13637c6a94..0284d17d06 100644 --- a/execution_engine/src/runtime/handle_payment_internal.rs +++ b/execution_engine/src/runtime/handle_payment_internal.rs @@ -2,9 +2,8 @@ use casper_storage::global_state::{error::Error as GlobalStateError, state::Stat use std::collections::BTreeSet; use casper_types::{ - account::AccountHash, addressable_entity::NamedKeyAddr, system::handle_payment::Error, - BlockTime, CLValue, FeeHandling, Key, Phase, RefundHandling, StoredValue, TransferredTo, URef, - U512, + account::AccountHash, addressable_entity::NamedKeyAddr, system::handle_payment::Error, CLValue, + FeeHandling, HoldsEpoch, Key, Phase, RefundHandling, StoredValue, TransferredTo, URef, U512, }; use casper_storage::system::handle_payment::{ @@ -64,8 +63,12 @@ where } } - fn balance(&mut self, purse: URef) -> Result, Error> { - self.get_balance(purse) + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { + Runtime::available_balance(self, purse, holds_epoch) .map_err(|exec_error| >::from(exec_error).unwrap_or(Error::GetBalance)) } @@ -129,15 +132,11 @@ where self.context.phase() } - fn get_block_time(&self) -> BlockTime { - self.context.get_blocktime() - } - fn get_caller(&self) -> AccountHash { self.context.get_caller() } - fn refund_handling(&self) -> &RefundHandling { + fn refund_handling(&self) -> RefundHandling { self.context.engine_config().refund_handling() } @@ -145,8 +144,11 @@ where self.context.engine_config().fee_handling() } - fn administrative_accounts(&self) -> &BTreeSet { - self.context.engine_config().administrative_accounts() + fn administrative_accounts(&self) -> BTreeSet { + self.context + .engine_config() + .administrative_accounts() + .clone() } } diff --git a/execution_engine/src/runtime/mint_internal.rs b/execution_engine/src/runtime/mint_internal.rs index 8607a6eed4..9bbeb0e079 100644 --- a/execution_engine/src/runtime/mint_internal.rs +++ b/execution_engine/src/runtime/mint_internal.rs @@ -14,7 +14,8 @@ use casper_types::{ account::AccountHash, bytesrepr::{FromBytes, ToBytes}, system::{mint::Error, Caller}, - AddressableEntity, CLTyped, CLValue, Key, Phase, StoredValue, SystemEntityRegistry, URef, U512, + AddressableEntity, CLTyped, CLValue, HoldsEpoch, Key, Phase, StoredValue, SystemEntityRegistry, + URef, U512, }; use super::Runtime; @@ -72,9 +73,9 @@ where } fn get_system_entity_registry(&self) -> Result { - self.context.system_contract_registry().map_err(|err| { - error!(%err, "unable to obtain system contract registry during transfer"); - ProviderError::SystemContractRegistry + self.context.system_entity_registry().map_err(|err| { + error!(%err, "unable to obtain system entity registry during transfer"); + ProviderError::SystemEntityRegistry }) } @@ -140,19 +141,13 @@ where .map_err(|exec_error| >::from(exec_error).unwrap_or(Error::Storage)) } - fn read_balance(&mut self, uref: URef) -> Result, Error> { - let maybe_value = self - .context - .read_gs_direct(&Key::Balance(uref.addr())) - .map_err(|exec_error| >::from(exec_error).unwrap_or(Error::Storage))?; - match maybe_value { - Some(StoredValue::CLValue(value)) => { - let value = CLValue::into_t(value).map_err(|_| Error::CLValue)?; - Ok(Some(value)) - } - Some(_cl_value) => Err(Error::CLValue), - None => Ok(None), - } + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { + Runtime::available_balance(self, purse, holds_epoch) + .map_err(|exec_error| >::from(exec_error).unwrap_or(Error::Storage)) } fn write_balance(&mut self, uref: URef, balance: U512) -> Result<(), Error> { diff --git a/execution_engine/src/runtime/mod.rs b/execution_engine/src/runtime/mod.rs index 7a2899f18f..2b2ea44e9c 100644 --- a/execution_engine/src/runtime/mod.rs +++ b/execution_engine/src/runtime/mod.rs @@ -42,7 +42,6 @@ use casper_types::{ }, contracts::ContractPackage, crypto, - package::PackageStatus, system::{ self, auction::{self, EraInfo}, @@ -50,11 +49,11 @@ use casper_types::{ STANDARD_PAYMENT, }, AccessRights, ApiError, BlockTime, ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind, CLTyped, - CLValue, ContextAccessRights, ContractWasm, DeployHash, EntityAddr, EntityKind, EntityVersion, - EntityVersionKey, EntityVersions, Gas, GrantedAccess, Group, Groups, HostFunction, - HostFunctionCost, Key, NamedArg, Package, PackageHash, Phase, PublicKey, RuntimeArgs, - StoredValue, Tagged, Transfer, TransferResult, TransferredTo, URef, - DICTIONARY_ITEM_KEY_MAX_LENGTH, U512, + CLValue, ContextAccessRights, ContractWasm, EntityAddr, EntityKind, EntityVersion, + EntityVersionKey, EntityVersions, Gas, GrantedAccess, Group, Groups, HoldsEpoch, HostFunction, + HostFunctionCost, InitiatorAddr, Key, NamedArg, Package, PackageHash, PackageStatus, Phase, + PublicKey, RuntimeArgs, StoredValue, Tagged, Transfer, TransferResult, TransferV2, + TransferredTo, URef, DICTIONARY_ITEM_KEY_MAX_LENGTH, U512, }; use crate::{ @@ -397,7 +396,7 @@ where return true; } - if let Some(Caller::Session { account_hash }) = self.get_immediate_caller() { + if let Some(Caller::Initiator { account_hash }) = self.get_immediate_caller() { return account_hash == provided_account_hash; } false @@ -555,6 +554,14 @@ where } } + /// Returns holds epoch. + fn holds_epoch(&self) -> HoldsEpoch { + HoldsEpoch::from_block_time( + self.context.get_blocktime(), + self.context.engine_config().balance_hold_interval, + ) + } + /// Calls host mint contract. fn call_host_mint( &mut self, @@ -566,7 +573,7 @@ where let gas_counter = self.gas_counter(); let mint_hash = self.context.get_system_contract(MINT)?; - let mint_addr = EntityAddr::new_system_entity_addr(mint_hash.value()); + let mint_addr = EntityAddr::new_system(mint_hash.value()); let mint_named_keys = self .context @@ -578,7 +585,7 @@ where let runtime_context = self.context.new_from_self( mint_addr.into(), - EntryPointType::AddressableEntity, + EntryPointType::Called, &mut named_keys, access_rights, runtime_args.to_owned(), @@ -621,8 +628,11 @@ where mint_runtime.charge_system_contract_call(mint_costs.balance)?; let uref: URef = Self::get_named_argument(runtime_args, mint::ARG_PURSE)?; - let maybe_balance: Option = - mint_runtime.balance(uref).map_err(Self::reverter)?; + let holds_epoch = self.holds_epoch(); + + let maybe_balance: Option = mint_runtime + .balance(uref, holds_epoch) + .map_err(Self::reverter)?; CLValue::from_t(maybe_balance).map_err(Self::reverter) })(), // Type: `fn transfer(maybe_to: Option, source: URef, target: URef, amount: @@ -636,8 +646,9 @@ where let target: URef = Self::get_named_argument(runtime_args, mint::ARG_TARGET)?; let amount: U512 = Self::get_named_argument(runtime_args, mint::ARG_AMOUNT)?; let id: Option = Self::get_named_argument(runtime_args, mint::ARG_ID)?; + let holds_epoch = self.holds_epoch(); let result: Result<(), mint::Error> = - mint_runtime.transfer(maybe_to, source, target, amount, id); + mint_runtime.transfer(maybe_to, source, target, amount, id, holds_epoch); CLValue::from_t(result).map_err(Self::reverter) })(), @@ -667,10 +678,12 @@ where // Charge just for the amount that particular entry point cost - using gas cost from the // isolated runtime might have a recursive costs whenever system contract calls other system // contract. - self.gas(match mint_runtime.gas_counter().checked_sub(gas_counter) { - None => gas_counter, - Some(new_gas) => new_gas, - })?; + self.gas( + mint_runtime + .gas_counter() + .checked_sub(gas_counter) + .unwrap_or(gas_counter), + )?; // Result still contains a result, but the entrypoints logic does not exit early on errors. let ret = result?; @@ -712,7 +725,7 @@ where let runtime_context = self.context.new_from_self( handle_payment_key, - EntryPointType::AddressableEntity, + EntryPointType::Called, &mut named_keys, access_rights, runtime_args.to_owned(), @@ -746,36 +759,15 @@ where let maybe_purse = runtime.get_refund_purse().map_err(Self::reverter)?; CLValue::from_t(maybe_purse).map_err(Self::reverter) })(), - handle_payment::METHOD_FINALIZE_PAYMENT => (|| { - runtime.charge_system_contract_call(handle_payment_costs.finalize_payment)?; - - let amount_spent: U512 = - Self::get_named_argument(runtime_args, handle_payment::ARG_AMOUNT)?; - let account: AccountHash = - Self::get_named_argument(runtime_args, handle_payment::ARG_ACCOUNT)?; - let target: URef = - Self::get_named_argument(runtime_args, handle_payment::ARG_TARGET)?; - runtime - .finalize_payment(amount_spent, account, target) - .map_err(Self::reverter)?; - - CLValue::from_t(()).map_err(Self::reverter) - })(), - handle_payment::METHOD_DISTRIBUTE_ACCUMULATED_FEES => (|| { - runtime.charge_system_contract_call(handle_payment_costs.finalize_payment)?; - runtime - .distribute_accumulated_fees() - .map_err(Self::reverter)?; - CLValue::from_t(()).map_err(Self::reverter) - })(), - _ => CLValue::from_t(()).map_err(Self::reverter), }; - self.gas(match runtime.gas_counter().checked_sub(gas_counter) { - None => gas_counter, - Some(new_gas) => new_gas, - })?; + self.gas( + runtime + .gas_counter() + .checked_sub(gas_counter) + .unwrap_or(gas_counter), + )?; let ret = result?; @@ -811,7 +803,7 @@ where let runtime_context = self.context.new_from_self( auction_key, - EntryPointType::AddressableEntity, + EntryPointType::Called, &mut named_keys, access_rights, runtime_args.to_owned(), @@ -836,14 +828,14 @@ where auction::METHOD_ADD_BID => (|| { runtime.charge_system_contract_call(auction_costs.add_bid)?; - let account_hash = Self::get_named_argument(runtime_args, auction::ARG_PUBLIC_KEY)?; let delegation_rate = Self::get_named_argument(runtime_args, auction::ARG_DELEGATION_RATE)?; let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + let holds_epoch = self.holds_epoch(); let result = runtime - .add_bid(account_hash, delegation_rate, amount) + .add_bid(account_hash, delegation_rate, amount, holds_epoch) .map_err(Self::reverter)?; CLValue::from_t(result).map_err(Self::reverter) @@ -872,7 +864,7 @@ where self.context.engine_config().max_delegators_per_validator(); let minimum_delegation_amount = self.context.engine_config().minimum_delegation_amount(); - + let holds_epoch = self.holds_epoch(); let result = runtime .delegate( delegator, @@ -880,6 +872,7 @@ where amount, max_delegators_per_validator, minimum_delegation_amount, + holds_epoch, ) .map_err(Self::reverter)?; @@ -985,12 +978,9 @@ where auction::METHOD_ACTIVATE_BID => (|| { runtime.charge_system_contract_call(auction_costs.activate_bid)?; - let validator_public_key: PublicKey = - Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR_PUBLIC_KEY)?; + let validator = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; - runtime - .activate_bid(validator_public_key) - .map_err(Self::reverter)?; + runtime.activate_bid(validator).map_err(Self::reverter)?; CLValue::from_t(()).map_err(Self::reverter) })(), @@ -999,10 +989,12 @@ where }; // Charge for the gas spent during execution in an isolated runtime. - self.gas(match runtime.gas_counter().checked_sub(gas_counter) { - None => gas_counter, - Some(new_gas) => new_gas, - })?; + self.gas( + runtime + .gas_counter() + .checked_sub(gas_counter) + .unwrap_or(gas_counter), + )?; // Result still contains a result, but the entrypoints logic does not exit early on errors. let ret = result?; @@ -1073,15 +1065,13 @@ where // this is normal operation and we should return the value captured // in the Runtime result field. let downcasted_error = host_error.downcast_ref::(); - match downcasted_error { - Some(ExecError::Ret(ref _ret_urefs)) => { - return self - .take_host_buffer() - .ok_or(ExecError::ExpectedReturnValue); - } - Some(error) => return Err(error.clone()), - None => return Err(ExecError::Interpreter(host_error.to_string())), - } + return match downcasted_error { + Some(ExecError::Ret(ref _ret_urefs)) => self + .take_host_buffer() + .ok_or(ExecError::ExpectedReturnValue), + Some(error) => Err(error.clone()), + None => Err(ExecError::Interpreter(host_error.to_string())), + }; } Err(ExecError::Interpreter(error.into())) } @@ -1124,25 +1114,23 @@ where let current = self.context.entry_point_type(); let next = entry_point.entry_point_type(); match (current, next) { - (EntryPointType::AddressableEntity, EntryPointType::Session) => { + (EntryPointType::Called, EntryPointType::Caller) => { // Session code can't be called from Contract code for security reasons. Err(ExecError::InvalidContext) } - (EntryPointType::Factory, EntryPointType::Session) => { + (EntryPointType::Factory, EntryPointType::Caller) => { // Session code can't be called from Installer code for security reasons. Err(ExecError::InvalidContext) } - (EntryPointType::Session, EntryPointType::Session) => { + (EntryPointType::Caller, EntryPointType::Caller) => { // Session code called from session reuses current base key match self.context.get_entity_key().into_entity_hash() { Some(entity_hash) => Ok(entity_hash), None => Err(ExecError::InvalidEntity(entity_hash)), } } - (EntryPointType::Session, EntryPointType::AddressableEntity) - | (EntryPointType::AddressableEntity, EntryPointType::AddressableEntity) => { - Ok(entity_hash) - } + (EntryPointType::Caller, EntryPointType::Called) + | (EntryPointType::Called, EntryPointType::Called) => Ok(entity_hash), _ => { // Any other combination (installer, normal, etc.) is a contract context. Ok(entity_hash) @@ -1256,7 +1244,7 @@ where } }; - if let EntityKind::Account(_) = entity.entity_kind() { + if let EntityKind::Account(_) = entity.kind() { return Err(ExecError::InvalidContext); } @@ -1377,7 +1365,7 @@ where all_urefs }; - let entity_addr = EntityAddr::new_with_tag(entity.entity_kind(), entity_hash.value()); + let entity_addr = entity.entity_addr(entity_hash); let entity_named_keys = self .context @@ -1394,12 +1382,12 @@ where let stack = { let mut stack = self.try_get_stack()?.clone(); - stack.push(Caller::stored_contract(entity.package_hash(), entity_hash))?; + stack.push(Caller::entity(entity.package_hash(), entity_hash))?; stack }; - if let EntityKind::System(system_contract_type) = entity.entity_kind() { + if let EntityKind::System(system_contract_type) = entity.kind() { let entry_point_name = entry_point.name(); match system_contract_type { @@ -1435,7 +1423,7 @@ where let module: Module = { let byte_code_addr = entity.byte_code_addr(); - let byte_code_key = match entity.entity_kind() { + let byte_code_key = match entity.kind() { EntityKind::System(_) | EntityKind::Account(_) => { Key::ByteCode(ByteCodeAddr::Empty) } @@ -1453,7 +1441,7 @@ where casper_wasm::deserialize_buffer(byte_code.bytes())? }; - let entity_tag = entity.entity_kind().tag(); + let entity_tag = entity.kind().tag(); let mut named_keys = entity_named_keys; @@ -1504,7 +1492,7 @@ where // operation and we should return the value captured in the Runtime result // field. let downcasted_error = host_error.downcast_ref::(); - match downcasted_error { + return match downcasted_error { Some(ExecError::Ret(ref ret_urefs)) => { // Insert extra urefs returned from call. // Those returned URef's are guaranteed to be valid as they were already @@ -1513,13 +1501,13 @@ where // Stored contracts are expected to always call a `ret` function, // otherwise it's an error. - return runtime + runtime .take_host_buffer() - .ok_or(ExecError::ExpectedReturnValue); + .ok_or(ExecError::ExpectedReturnValue) } - Some(error) => return Err(error.clone()), - None => return Err(ExecError::Interpreter(host_error.to_string())), - } + Some(error) => Err(error.clone()), + None => Err(ExecError::Interpreter(host_error.to_string())), + }; } Err(ExecError::Interpreter(error.into())) } @@ -1756,6 +1744,10 @@ where message_topics: BTreeMap, output_ptr: u32, ) -> Result, ExecError> { + if !self.context.allow_casper_add_contract_version() { + return Ok(Err(ApiError::NotAllowedToAddContractVersion)); + } + if entry_points.contains_stored_session() { return Err(ExecError::InvalidEntryPointType); } @@ -1824,7 +1816,7 @@ where byte_code, )?; - let entity_addr = EntityAddr::new_contract_entity_addr(entity_hash); + let entity_addr = EntityAddr::new_smart_contract(entity_hash); let entity_key = Key::AddressableEntity(entity_addr); @@ -2048,19 +2040,13 @@ where return Ok(()); } - let transfer_addr = self.context.new_transfer_addr()?; - let transfer = { - let deploy_hash: DeployHash = self.context.get_deploy_hash(); - let from: AccountHash = self.context.get_caller(); - let fee: U512 = U512::zero(); // TODO - Transfer::new(deploy_hash, from, maybe_to, source, target, amount, fee, id) - }; - { - let transfers = self.context.transfers_mut(); - transfers.push(transfer_addr); - } - self.context - .write_transfer(Key::Transfer(transfer_addr), transfer); + let txn_hash = self.context.get_transaction_hash(); + let from = InitiatorAddr::AccountHash(self.context.get_caller()); + let fee = Gas::zero(); // TODO + let transfer = Transfer::V2(TransferV2::new( + txn_hash, from, maybe_to, source, target, amount, fee, id, + )); + self.context.transfers_mut().push(transfer); Ok(()) } @@ -2449,9 +2435,14 @@ where return Err(ExecError::DisabledUnrestrictedTransfers); } + let holds_epoch = self.holds_epoch(); // A precondition check that verifies that the transfer can be done // as the source purse has enough funds to cover the transfer. - if amount > self.get_balance(source)?.unwrap_or_default() { + if amount + > self + .available_balance(source, holds_epoch)? + .unwrap_or_default() + { return Ok(Err(mint::Error::InsufficientFunds.into())); } @@ -2588,9 +2579,9 @@ where self.transfer_to_new_account(source, target, amount, id) } - Some(StoredValue::CLValue(account)) => { + Some(StoredValue::CLValue(entity_key_value)) => { // Attenuate the target main purse - let entity_key = CLValue::into_t::(account)?; + let entity_key = CLValue::into_t::(entity_key_value)?; let target_uref = if let Some(StoredValue::AddressableEntity(entity)) = self.context.read_gs(&entity_key)? { @@ -2700,15 +2691,14 @@ where } } - fn get_balance(&mut self, purse: URef) -> Result, ExecError> { - let maybe_value = self.context.read_gs_direct(&Key::Balance(purse.addr()))?; - match maybe_value { - Some(StoredValue::CLValue(value)) => { - let value = CLValue::into_t(value)?; - Ok(Some(value)) - } - Some(_) => Err(ExecError::UnexpectedStoredValueVariant), - None => Ok(None), + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, ExecError> { + match self.context.available_balance(&purse, holds_epoch) { + Ok(motes) => Ok(Some(motes.value())), + Err(err) => Err(err), } } @@ -2731,7 +2721,7 @@ where } }; - let balance = match self.get_balance(purse)? { + let balance = match self.available_balance(purse, self.holds_epoch())? { Some(balance) => balance, None => return Ok(Err(ApiError::InvalidPurse)), }; @@ -2810,7 +2800,7 @@ where Some(cl_value) => cl_value.destructure(), }; - if serialized_value.len() > u32::max_value() as usize { + if serialized_value.len() > u32::MAX as usize { return Ok(Err(ApiError::OutOfMemory)); } if serialized_value.len() > dest_size { @@ -2858,7 +2848,7 @@ where let name = String::from_utf8_lossy(&name_bytes); let arg_size: u32 = match self.context.args().get(&name) { - Some(arg) if arg.inner_bytes().len() > u32::max_value() as usize => { + Some(arg) if arg.inner_bytes().len() > u32::MAX as usize => { return Ok(Err(ApiError::OutOfMemory)); } Some(arg) => { @@ -3275,11 +3265,11 @@ where }; match immediate_caller { - Caller::Session { account_hash } => { + Caller::Initiator { account_hash } => { // This case can happen during genesis where we're setting up purses for accounts. Ok(account_hash == &PublicKey::System.to_account_hash()) } - Caller::AddressableEntity { + Caller::Entity { entity_hash: contract_hash, .. } => Ok(self.context.is_system_addressable_entity(contract_hash)?), @@ -3365,7 +3355,7 @@ where AssociatedKeys::default() }; - let contract_addr = EntityAddr::new_contract_entity_addr(contract_hash.value()); + let contract_addr = EntityAddr::new_smart_contract(contract_hash.value()); self.context .write_named_keys(contract_addr, contract.named_keys().clone())?; @@ -3489,8 +3479,7 @@ where #[cfg(feature = "test-support")] fn dump_runtime_stack_info(instance: casper_wasmi::ModuleRef, max_stack_height: u32) { let globals = instance.globals(); - let Some(current_runtime_call_stack_height) = globals.last() - else { + let Some(current_runtime_call_stack_height) = globals.last() else { return; }; diff --git a/execution_engine/src/runtime/stack.rs b/execution_engine/src/runtime/stack.rs index 153f12a4a8..824ecea251 100644 --- a/execution_engine/src/runtime/stack.rs +++ b/execution_engine/src/runtime/stack.rs @@ -1,6 +1,5 @@ //! Runtime stacks. - -use casper_types::{account::AccountHash, system::Caller, PublicKey}; +use casper_types::{account::AccountHash, system::Caller}; /// A runtime stack frame. /// @@ -42,14 +41,6 @@ impl RuntimeStack { Self { frames, max_height } } - /// Creates a new call instance that starts with a system account. - pub(crate) fn new_system_call_stack(max_height: usize) -> Self { - RuntimeStack::new_with_frame( - max_height, - Caller::session(PublicKey::System.to_account_hash()), - ) - } - /// Is the stack empty? pub fn is_empty(&self) -> bool { self.frames.is_empty() @@ -101,7 +92,7 @@ impl RuntimeStack { /// Returns a stack with exactly one session element with the associated account hash. pub fn from_account_hash(account_hash: AccountHash, max_height: usize) -> Self { RuntimeStack { - frames: vec![Caller::session(account_hash)], + frames: vec![Caller::initiator(account_hash)], max_height, } } @@ -119,7 +110,7 @@ mod test { let mut bytes = [0_u8; ACCOUNT_HASH_LENGTH]; let n: u32 = n.try_into().unwrap(); bytes[0..4].copy_from_slice(&n.to_le_bytes()); - Caller::session(AccountHash::new(bytes)) + Caller::initiator(AccountHash::new(bytes)) } #[allow(clippy::redundant_clone)] diff --git a/execution_engine/src/runtime_context/mod.rs b/execution_engine/src/runtime_context/mod.rs index d3b88098f5..59fc793d2e 100644 --- a/execution_engine/src/runtime_context/mod.rs +++ b/execution_engine/src/runtime_context/mod.rs @@ -22,8 +22,8 @@ use casper_storage::{ use casper_types::{ account::{Account, AccountHash}, addressable_entity::{ - ActionType, AddKeyFailure, EntityKind, EntityKindTag, MessageTopicError, NamedKeyAddr, - NamedKeyValue, NamedKeys, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure, Weight, + ActionType, AddKeyFailure, EntityKindTag, MessageTopicError, NamedKeyAddr, NamedKeyValue, + NamedKeys, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure, Weight, }, bytesrepr::ToBytes, contract_messages::{Message, MessageAddr, MessageTopicSummary, Messages, TopicNameHash}, @@ -31,10 +31,10 @@ use casper_types::{ handle_stored_dictionary_value, system::auction::EraInfo, AccessRights, AddressableEntity, AddressableEntityHash, BlockTime, CLType, CLValue, - CLValueDictionary, ContextAccessRights, DeployHash, EntityAddr, EntryPointType, Gas, - GrantedAccess, Key, KeyTag, Package, PackageHash, Phase, ProtocolVersion, PublicKey, - RuntimeArgs, StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, Transfer, - TransferAddr, URef, URefAddr, DICTIONARY_ITEM_KEY_MAX_LENGTH, KEY_HASH_LENGTH, U512, + CLValueDictionary, ContextAccessRights, EntityAddr, EntryPointType, Gas, GrantedAccess, + HoldsEpoch, Key, KeyTag, Motes, Package, PackageHash, Phase, ProtocolVersion, PublicKey, + RuntimeArgs, StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, TransactionHash, + Transfer, URef, URefAddr, DICTIONARY_ITEM_KEY_MAX_LENGTH, KEY_HASH_LENGTH, U512, }; use crate::{engine_state::EngineConfig, execution::ExecError}; @@ -42,6 +42,15 @@ use crate::{engine_state::EngineConfig, execution::ExecError}; /// Number of bytes returned from the `random_bytes` function. pub const RANDOM_BYTES_COUNT: usize = 32; +/// Whether the execution is permitted to call FFI `casper_add_contract_version()` or not. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum CallingAddContractVersion { + /// Allowed. + Allowed, + /// Forbidden. + Forbidden, +} + /// Holds information specific to the deployed contract. pub struct RuntimeContext<'a, R> { tracking_copy: Rc>>, @@ -52,7 +61,7 @@ pub struct RuntimeContext<'a, R> { args: RuntimeArgs, authorization_keys: BTreeSet, blocktime: BlockTime, - deploy_hash: DeployHash, + transaction_hash: TransactionHash, gas_limit: Gas, gas_counter: Gas, address_generator: Rc>, @@ -61,16 +70,16 @@ pub struct RuntimeContext<'a, R> { engine_config: EngineConfig, //TODO: Will be removed along with stored session in later PR. entry_point_type: EntryPointType, - transfers: Vec, + transfers: Vec, remaining_spending_limit: U512, // Original account/contract for read only tasks taken before execution entity: &'a AddressableEntity, // Key pointing to the entity we are currently running entity_key: Key, - entity_kind: EntityKind, account_hash: AccountHash, emit_message_cost: U512, + calling_add_contract_version: CallingAddContractVersion, } impl<'a, R> RuntimeContext<'a, R> @@ -87,21 +96,21 @@ where entity_key: Key, authorization_keys: BTreeSet, access_rights: ContextAccessRights, - entity_kind: EntityKind, account_hash: AccountHash, address_generator: Rc>, tracking_copy: Rc>>, engine_config: EngineConfig, blocktime: BlockTime, protocol_version: ProtocolVersion, - deploy_hash: DeployHash, + transaction_hash: TransactionHash, phase: Phase, - runtime_args: RuntimeArgs, + args: RuntimeArgs, gas_limit: Gas, gas_counter: Gas, - transfers: Vec, + transfers: Vec, remaining_spending_limit: U512, entry_point_type: EntryPointType, + calling_add_contract_version: CallingAddContractVersion, ) -> Self { let emit_message_cost = engine_config .wasm_config() @@ -114,13 +123,13 @@ where entry_point_type, named_keys, access_rights, - args: runtime_args, + args, entity, entity_key, authorization_keys, account_hash, blocktime, - deploy_hash, + transaction_hash, gas_limit, gas_counter, address_generator, @@ -129,8 +138,8 @@ where engine_config, transfers, remaining_spending_limit, - entity_kind, emit_message_cost, + calling_add_contract_version, } } @@ -147,7 +156,6 @@ where let entity = self.entity; let authorization_keys = self.authorization_keys.clone(); let account_hash = self.account_hash; - let entity_kind = self.entity_kind; let address_generator = self.address_generator.clone(); let tracking_copy = self.state(); @@ -155,7 +163,7 @@ where let blocktime = self.blocktime; let protocol_version = self.protocol_version; - let deploy_hash = self.deploy_hash; + let transaction_hash = self.transaction_hash; let phase = self.phase; let gas_limit = self.gas_limit; @@ -175,7 +183,7 @@ where authorization_keys, account_hash, blocktime, - deploy_hash, + transaction_hash, gas_limit, gas_counter, address_generator, @@ -184,8 +192,8 @@ where engine_config, transfers, remaining_spending_limit, - entity_kind, emit_message_cost: self.emit_message_cost, + calling_add_contract_version: self.calling_add_contract_version, } } @@ -219,30 +227,27 @@ where &self.engine_config } - /// Returns the package kind associated with the current context. - pub fn get_entity_kind(&self) -> EntityKind { - self.entity_kind - } - /// Returns whether the current context is of the system addressable entity. pub fn is_system_account(&self) -> bool { - if let Some(account_hash) = self.entity_kind.maybe_account_hash() { - return account_hash == PublicKey::System.to_account_hash(); + if let Key::AddressableEntity(entity_addr) = self.entity_key { + entity_addr.value() == PublicKey::System.to_account_hash().value() + } else { + false } - false } /// Helper function to avoid duplication in `remove_uref`. - fn remove_key_from_entity(&mut self, entity_key: Key, name: &str) -> Result<(), ExecError> { - let entity_addr = if let Key::AddressableEntity(addr) = entity_key { - addr - } else { - return Err(ExecError::UnexpectedKeyVariant(entity_key)); - }; - - let named_key_addr = NamedKeyAddr::new_from_string(entity_addr, name.to_string())?; - if let Some(StoredValue::NamedKey(_)) = self.read_gs(&Key::NamedKey(named_key_addr))? { - self.prune_gs_unsafe(Key::NamedKey(named_key_addr)); + fn remove_key_from_entity(&mut self, name: &str) -> Result<(), ExecError> { + let key = self.entity_key; + match key.as_entity_addr() { + None => return Err(ExecError::UnexpectedKeyVariant(key)), + Some(entity_addr) => { + let named_key = + NamedKeyAddr::new_from_string(entity_addr, name.to_string())?.into(); + if let Some(StoredValue::NamedKey(_)) = self.read_gs(&named_key)? { + self.prune_gs_unsafe(named_key); + } + } } Ok(()) } @@ -252,9 +257,8 @@ where /// also persistable map (one that is found in the /// TrackingCopy/GlobalState). pub fn remove_key(&mut self, name: &str) -> Result<(), ExecError> { - let entity_key = self.get_entity_key(); self.named_keys.remove(name); - self.remove_key_from_entity(entity_key, name) + self.remove_key_from_entity(name) } /// Returns the block time. @@ -262,9 +266,9 @@ where self.blocktime } - /// Returns the deploy hash. - pub fn get_deploy_hash(&self) -> DeployHash { - self.deploy_hash + /// Returns the transaction hash. + pub fn get_transaction_hash(&self) -> TransactionHash { + self.transaction_hash } /// Extends access rights with a new map. @@ -321,7 +325,7 @@ where self.entity_key } - /// Returns the initiater of the call chain. + /// Returns the initiator of the call chain. pub fn get_caller(&self) -> AccountHash { self.account_hash } @@ -336,6 +340,11 @@ where self.phase } + /// Returns `true` if the execution is permitted to call `casper_add_contract_version()`. + pub fn allow_casper_add_contract_version(&self) -> bool { + self.calling_add_contract_version == CallingAddContractVersion::Allowed + } + /// Generates new deterministic hash for uses as an address. pub fn new_hash_address(&mut self) -> Result<[u8; KEY_HASH_LENGTH], ExecError> { Ok(self.address_generator.borrow_mut().new_hash_address()) @@ -362,12 +371,6 @@ where self.new_uref(StoredValue::CLValue(CLValue::unit())) } - /// Creates a new transfer address using a transfer address generator. - pub fn new_transfer_addr(&mut self) -> Result { - let transfer_addr = self.address_generator.borrow_mut().create_address(); - Ok(TransferAddr::new(transfer_addr)) - } - /// Puts `key` to the map of named keys of current context. pub fn put_key(&mut self, name: String, key: Key) -> Result<(), ExecError> { // No need to perform actual validation on the base key because an account or contract (i.e. @@ -422,31 +425,25 @@ where /// Reads the balance of a purse [`URef`]. /// /// Currently address of a purse [`URef`] is also a hash in the [`Key::Hash`] space. - #[cfg(test)] - pub(crate) fn read_purse_uref( + pub(crate) fn available_balance( &mut self, purse_uref: &URef, - ) -> Result, ExecError> { - match self - .tracking_copy + holds_epoch: HoldsEpoch, + ) -> Result { + let key = Key::URef(*purse_uref); + self.tracking_copy .borrow_mut() - .read(&Key::Hash(purse_uref.addr())) - .map_err(ExecError::TrackingCopy)? - { - Some(stored_value) => Ok(Some( - stored_value.try_into().map_err(ExecError::TypeMismatch)?, - )), - None => Ok(None), - } + .get_available_balance(key, holds_epoch) + .map_err(ExecError::TrackingCopy) } #[cfg(test)] - pub(crate) fn write_purse_uref( + pub(crate) fn write_balance( &mut self, purse_uref: URef, cl_value: CLValue, ) -> Result<(), ExecError> { - self.metered_write_gs_unsafe(Key::Hash(purse_uref.addr()), cl_value) + self.metered_write_gs_unsafe(Key::Balance(purse_uref.addr()), cl_value) } /// Read a stored value under a [`Key`]. @@ -470,7 +467,7 @@ where /// /// DO NOT EXPOSE THIS VIA THE FFI - This function bypasses security checks and should be used /// with caution. - pub fn read_gs_direct(&mut self, key: &Key) -> Result, ExecError> { + pub fn read_gs_unsafe(&mut self, key: &Key) -> Result, ExecError> { self.tracking_copy .borrow_mut() .read(key) @@ -516,18 +513,6 @@ where .map_err(Into::into) } - /// Write a transfer instance to the global state. - pub fn write_transfer(&mut self, key: Key, value: Transfer) { - if let Key::Transfer(_) = key { - // Writing a `Transfer` will not exceed write size limit. - self.tracking_copy - .borrow_mut() - .write(key, StoredValue::Transfer(value)); - } else { - panic!("Do not use this function for writing non-transfer keys") - } - } - /// Write an era info instance to the global state. pub fn write_era_info(&mut self, key: Key, value: EraInfo) { if let Key::EraSummary = key { @@ -621,12 +606,12 @@ where } /// Returns list of transfers. - pub fn transfers(&self) -> &Vec { + pub fn transfers(&self) -> &Vec { &self.transfers } /// Returns mutable list of transfers. - pub fn transfers_mut(&mut self) -> &mut Vec { + pub fn transfers_mut(&mut self) -> &mut Vec { &mut self.transfers } @@ -672,27 +657,26 @@ where fn validate_value(&self, value: &StoredValue) -> Result<(), ExecError> { match value { StoredValue::CLValue(cl_value) => self.validate_cl_value(cl_value), - StoredValue::Account(_) => Ok(()), - StoredValue::ByteCode(_) => Ok(()), - StoredValue::Contract(_) => Ok(()), - StoredValue::AddressableEntity(_) => Ok(()), - // TODO: anything to validate here? - StoredValue::Package(_) => Ok(()), - StoredValue::Transfer(_) => Ok(()), - StoredValue::DeployInfo(_) => Ok(()), - StoredValue::EraInfo(_) => Ok(()), - StoredValue::Bid(_) => Ok(()), - StoredValue::BidKind(_) => Ok(()), - StoredValue::Withdraw(_) => Ok(()), - StoredValue::Unbonding(_) => Ok(()), - StoredValue::ContractPackage(_) => Ok(()), - StoredValue::ContractWasm(_) => Ok(()), - StoredValue::MessageTopic(_) => Ok(()), - StoredValue::Message(_) => Ok(()), StoredValue::NamedKey(named_key_value) => { self.validate_cl_value(named_key_value.get_key_as_cl_value())?; self.validate_cl_value(named_key_value.get_name_as_cl_value()) } + StoredValue::Account(_) + | StoredValue::ByteCode(_) + | StoredValue::Contract(_) + | StoredValue::AddressableEntity(_) + | StoredValue::Package(_) + | StoredValue::LegacyTransfer(_) + | StoredValue::DeployInfo(_) + | StoredValue::EraInfo(_) + | StoredValue::Bid(_) + | StoredValue::BidKind(_) + | StoredValue::Withdraw(_) + | StoredValue::Unbonding(_) + | StoredValue::ContractPackage(_) + | StoredValue::ContractWasm(_) + | StoredValue::MessageTopic(_) + | StoredValue::Message(_) => Ok(()), } } @@ -755,100 +739,34 @@ where /// Tests whether reading from the `key` is valid. pub fn is_readable(&self, key: &Key) -> bool { - match key { - Key::URef(uref) => uref.is_readable(), - Key::Balance(_) => false, - Key::Account(_) - | Key::Hash(_) - | Key::Transfer(_) - | Key::DeployInfo(_) - | Key::EraInfo(_) - | Key::Bid(_) - | Key::Withdraw(_) - | Key::Dictionary(_) - | Key::SystemEntityRegistry - | Key::EraSummary - | Key::Unbond(_) - | Key::ChainspecRegistry - | Key::ChecksumRegistry - | Key::BidAddr(_) - | Key::Package(_) - | Key::AddressableEntity(..) - | Key::ByteCode(..) - | Key::Message(_) - | Key::NamedKey(_) - | Key::BlockMessageCount => true, + match self.entity_key.as_entity_addr() { + Some(entity_addr) => key.is_readable(&entity_addr), + None => { + error!(?self.entity_key, "entity_key is unexpected key variant (expected Key::AddressableEntity)"); + panic!("is_readable: entity_key is unexpected key variant"); + } } } /// Tests whether addition to `key` is valid. pub fn is_addable(&self, key: &Key) -> bool { - match key { - Key::AddressableEntity(entity_addr) => match self.get_entity_key().into_entity_hash() { - Some(entity_hash) => entity_hash == AddressableEntityHash::new(entity_addr.value()), - None => false, - }, - Key::URef(uref) => uref.is_addable(), - Key::NamedKey(named_key_addr) => { - if let Key::AddressableEntity(entity_addr) = self.get_entity_key() { - named_key_addr.entity_addr() == entity_addr - } else { - false - } + match self.entity_key.as_entity_addr() { + Some(entity_addr) => key.is_addable(&entity_addr), + None => { + error!(?self.entity_key, "entity_key is unexpected key variant (expected Key::AddressableEntity)"); + panic!("is_addable: entity_key is unexpected key variant"); } - Key::Hash(_) - | Key::Account(_) - | Key::Transfer(_) - | Key::DeployInfo(_) - | Key::EraInfo(_) - | Key::Balance(_) - | Key::Bid(_) - | Key::Withdraw(_) - | Key::Dictionary(_) - | Key::SystemEntityRegistry - | Key::EraSummary - | Key::Unbond(_) - | Key::ChainspecRegistry - | Key::ChecksumRegistry - | Key::BidAddr(_) - | Key::Package(_) - | Key::ByteCode(..) - | Key::Message(_) - | Key::BlockMessageCount => false, } } /// Tests whether writing to `key` is valid. pub fn is_writeable(&self, key: &Key) -> bool { - match key { - Key::URef(uref) => uref.is_writeable(), - Key::NamedKey(named_key_addr) => { - if let Key::AddressableEntity(entity_addr) = self.get_entity_key() { - named_key_addr.entity_addr() == entity_addr - } else { - false - } + match self.entity_key.as_entity_addr() { + Some(entity_addr) => key.is_writeable(&entity_addr), + None => { + error!(?self.entity_key, "entity_key is unexpected key variant (expected Key::AddressableEntity)"); + panic!("is_writeable: entity_key is unexpected key variant"); } - Key::Account(_) - | Key::Hash(_) - | Key::Transfer(_) - | Key::DeployInfo(_) - | Key::EraInfo(_) - | Key::Balance(_) - | Key::Bid(_) - | Key::Withdraw(_) - | Key::Dictionary(_) - | Key::SystemEntityRegistry - | Key::EraSummary - | Key::Unbond(_) - | Key::ChainspecRegistry - | Key::ChecksumRegistry - | Key::BidAddr(_) - | Key::Package(_) - | Key::AddressableEntity(..) - | Key::ByteCode(..) - | Key::Message(_) - | Key::BlockMessageCount => false, } } @@ -860,10 +778,8 @@ where pub(crate) fn charge_gas(&mut self, gas: Gas) -> Result<(), ExecError> { let prev = self.gas_counter(); let gas_limit = self.gas_limit(); - let is_system = self.entity_kind.is_system(); - // gas charge overflow protection - match prev.checked_add(gas.cost(is_system)) { + match prev.checked_add(gas) { None => { self.set_gas_counter(gas_limit); Err(ExecError::GasLimit) @@ -885,7 +801,7 @@ where contract_hash: &AddressableEntityHash, ) -> Result { Ok(self - .system_contract_registry()? + .system_entity_registry()? .has_contract_hash(contract_hash)) } @@ -1046,26 +962,23 @@ where account_hash: AccountHash, weight: Weight, ) -> Result<(), ExecError> { - let entity_key = match self.entry_point_type { - EntryPointType::AddressableEntity => self.entity_key, - EntryPointType::Session | EntryPointType::Factory => { - self.get_entity_address_for_account_hash(self.account_hash)? - } + let entity_key = self.entity_key; + let entity_addr = match entity_key.as_entity_addr() { + Some(entity_addr) => entity_addr, + None => return Err(ExecError::UnexpectedKeyVariant(entity_key)), }; - // Check permission to modify associated keys - if !self.is_valid_context(entity_key) { + if EntryPointType::Caller == self.entry_point_type + && entity_addr.tag() != EntityKindTag::Account + { // Exit early with error to avoid mutations return Err(AddKeyFailure::PermissionDenied.into()); } - // Converts an account's public key into a URef - let key = self.get_entity_key(); - - // Take an addressable entity out of the global state + // Get the current entity record let entity = { - let mut entity: AddressableEntity = self.read_gs_typed(&key)?; - + let mut entity: AddressableEntity = self.read_gs_typed(&entity_key)?; + // enforce max keys limit if entity.associated_keys().len() >= (self.engine_config.max_associated_keys() as usize) { return Err(ExecError::AddKeyFailure(AddKeyFailure::MaxKeysLimit)); @@ -1078,9 +991,10 @@ where entity }; - let entity_value = self.addressable_entity_to_validated_value(entity)?; - - self.metered_write_gs_unsafe(key, entity_value)?; + self.metered_write_gs_unsafe( + entity_key, + self.addressable_entity_to_validated_value(entity)?, + )?; Ok(()) } @@ -1090,9 +1004,15 @@ where &mut self, account_hash: AccountHash, ) -> Result<(), ExecError> { - let entity_key = self.get_entity_address_for_account_hash(self.account_hash)?; - // Check permission to modify associated keys - if !self.is_valid_context(entity_key) { + let entity_key = self.entity_key; + let entity_addr = match entity_key.as_entity_addr() { + Some(entity_addr) => entity_addr, + None => return Err(ExecError::UnexpectedKeyVariant(entity_key)), + }; + + if EntryPointType::Caller == self.entry_point_type + && entity_addr.tag() != EntityKindTag::Account + { // Exit early with error to avoid mutations return Err(RemoveKeyFailure::PermissionDenied.into()); } @@ -1127,9 +1047,15 @@ where account_hash: AccountHash, weight: Weight, ) -> Result<(), ExecError> { - let entity_key = self.get_entity_address_for_account_hash(self.account_hash)?; - // Check permission to modify associated keys - if !self.is_valid_context(entity_key) { + let entity_key = self.entity_key; + let entity_addr = match entity_key.as_entity_addr() { + Some(entity_addr) => entity_addr, + None => return Err(ExecError::UnexpectedKeyVariant(entity_key)), + }; + + if EntryPointType::Caller == self.entry_point_type + && entity_addr.tag() != EntityKindTag::Account + { // Exit early with error to avoid mutations return Err(UpdateKeyFailure::PermissionDenied.into()); } @@ -1172,22 +1098,23 @@ where action_type: ActionType, threshold: Weight, ) -> Result<(), ExecError> { - let entity_key = match self.entry_point_type { - EntryPointType::AddressableEntity => self.entity_key, - EntryPointType::Session | EntryPointType::Factory => { - self.get_entity_address_for_account_hash(self.account_hash)? + let entity_key = self.entity_key; + let entity_addr = match entity_key.as_entity_addr() { + Some(entity_addr) => entity_addr, + None => { + return Err(ExecError::UnexpectedKeyVariant(entity_key)); } }; - // Check permission to modify associated keys - if !self.is_valid_context(entity_key) { + + if EntryPointType::Caller == self.entry_point_type + && entity_addr.tag() != EntityKindTag::Account + { // Exit early with error to avoid mutations return Err(SetThresholdFailure::PermissionDeniedError.into()); } - let key = self.get_entity_key(); - // Take an addressable entity out of the global state - let mut entity: AddressableEntity = self.read_gs_typed(&key)?; + let mut entity: AddressableEntity = self.read_gs_typed(&entity_key)?; // Exit early in case of error without updating global state if self.is_authorized_by_admin() { @@ -1199,7 +1126,7 @@ where let entity_value = self.addressable_entity_to_validated_value(entity)?; - self.metered_write_gs_unsafe(key, entity_value)?; + self.metered_write_gs_unsafe(entity_key, entity_value)?; Ok(()) } @@ -1213,14 +1140,6 @@ where Ok(value) } - pub(crate) fn get_entity_address_for_account_hash( - &mut self, - account_hash: AccountHash, - ) -> Result { - let cl_value = self.read_gs_typed::(&Key::Account(account_hash))?; - CLValue::into_t::(cl_value).map_err(ExecError::CLValue) - } - pub(crate) fn read_addressable_entity_by_account_hash( &mut self, account_hash: AccountHash, @@ -1241,11 +1160,6 @@ where } } - /// Checks if the account context is valid. - fn is_valid_context(&self, entity_key: Key) -> bool { - self.get_entity_key() == entity_key - } - /// Gets main purse id pub fn get_main_purse(&mut self) -> Result { let main_purse = self.entity().main_purse(); @@ -1383,7 +1297,7 @@ where &self, name: &str, ) -> Result { - let registry = self.system_contract_registry()?; + let registry = self.system_entity_registry()?; let hash = registry.get(name).ok_or_else(|| { error!("Missing system contract hash: {}", name); ExecError::MissingSystemContractHash(name.to_string()) @@ -1399,13 +1313,13 @@ where )) } - /// Returns system contract registry by querying the global state. - pub fn system_contract_registry(&self) -> Result { + /// Returns system entity registry by querying the global state. + pub fn system_entity_registry(&self) -> Result { self.tracking_copy .borrow_mut() .get_system_entity_registry() .map_err(|err| { - error!("Missing system contract registry"); + error!("Missing system entity registry"); ExecError::TrackingCopy(err) }) } diff --git a/execution_engine/src/runtime_context/tests.rs b/execution_engine/src/runtime_context/tests.rs index 0f939a234f..21e82b2d20 100644 --- a/execution_engine/src/runtime_context/tests.rs +++ b/execution_engine/src/runtime_context/tests.rs @@ -18,16 +18,17 @@ use casper_types::{ execution::TransformKindV2, system::{AUCTION, HANDLE_PAYMENT, MINT, STANDARD_PAYMENT}, AccessRights, AddressableEntity, AddressableEntityHash, BlockTime, ByteCodeHash, CLValue, - ContextAccessRights, DeployHash, EntityAddr, EntityKind, EntryPointType, EntryPoints, Gas, Key, + ContextAccessRights, EntityAddr, EntityKind, EntryPointType, EntryPoints, Gas, HoldsEpoch, Key, PackageHash, Phase, ProtocolVersion, PublicKey, RuntimeArgs, SecretKey, StoredValue, - SystemEntityRegistry, Tagged, URef, KEY_HASH_LENGTH, U256, U512, + SystemEntityRegistry, Tagged, TransactionHash, TransactionV1Hash, URef, KEY_HASH_LENGTH, U256, + U512, }; use tempfile::TempDir; -use super::{ExecError, RuntimeContext}; +use super::{CallingAddContractVersion, ExecError, RuntimeContext}; use crate::engine_state::EngineConfig; -const DEPLOY_HASH: [u8; 32] = [1u8; 32]; +const TXN_HASH_RAW: [u8; 32] = [1u8; 32]; const PHASE: Phase = Phase::Session; const GAS_LIMIT: u64 = 500_000_000_000_000u64; @@ -147,21 +148,21 @@ fn new_runtime_context<'a>( entity_address, BTreeSet::from_iter(vec![account_hash]), access_rights, - EntityKind::Account(account_hash), account_hash, Rc::new(RefCell::new(address_generator)), Rc::new(RefCell::new(tracking_copy)), TEST_ENGINE_CONFIG.clone(), BlockTime::new(0), ProtocolVersion::V1_0_0, - DeployHash::from_raw([1u8; 32]), + TransactionHash::V1(TransactionV1Hash::from_raw([1u8; 32])), Phase::Session, RuntimeArgs::new(), Gas::new(U512::from(GAS_LIMIT)), Gas::default(), Vec::default(), U512::MAX, - EntryPointType::Session, + EntryPointType::Caller, + CallingAddContractVersion::Forbidden, ); (runtime_context, tempdir) @@ -236,51 +237,51 @@ fn last_transform_kind_on_addressable_entity( #[test] fn use_uref_valid() { // Test fixture - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_as_key = create_uref_as_key(&mut rng, AccessRights::READ_WRITE); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_as_key); // Use uref as the key to perform an action on the global state. // This should succeed because the uref is valid. let value = StoredValue::CLValue(CLValue::from_t(43_i32).unwrap()); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { rc.metered_write_gs(uref_as_key, value) }); - query_result.expect("writing using valid uref should succeed"); + result.expect("writing using valid uref should succeed"); } #[test] fn use_uref_forged() { // Test fixture - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref = create_uref_as_key(&mut rng, AccessRights::READ_WRITE); let named_keys = NamedKeys::new(); // named_keys.insert(String::new(), Key::from(uref)); let value = StoredValue::CLValue(CLValue::from_t(43_i32).unwrap()); - let query_result = + let result = build_runtime_context_and_execute(named_keys, |mut rc| rc.metered_write_gs(uref, value)); - assert_forged_reference(query_result); + assert_forged_reference(result); } #[test] fn account_key_not_writeable() { let mut rng = rand::thread_rng(); let acc_key = random_account_key(&mut rng); - let query_result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { + let result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { rc.metered_write_gs( acc_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert_invalid_access(query_result, AccessRights::WRITE); + assert_invalid_access(result, AccessRights::WRITE); } #[test] fn entity_key_readable_valid() { // Entity key is readable if it is a "base" key - current context of the // execution. - let query_result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { + let result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { let base_key = rc.get_entity_key(); let entity = rc.get_entity(); @@ -293,18 +294,18 @@ fn entity_key_readable_valid() { Ok(()) }); - assert!(query_result.is_ok()); + assert!(result.is_ok()); } #[test] fn account_key_addable_returns_type_mismatch() { // Account key is not addable anymore as we do not store an account underneath they key // but instead there is a CLValue which acts as an indirection to the corresponding entity. - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_as_key = create_uref_as_key(&mut rng, AccessRights::READ); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_as_key); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { let account_key: Key = rc.account_hash.into(); let uref_name = "NewURef".to_owned(); let named_key = StoredValue::CLValue(CLValue::from_t((uref_name, uref_as_key)).unwrap()); @@ -312,7 +313,7 @@ fn account_key_addable_returns_type_mismatch() { rc.metered_add_gs(account_key, named_key) }); - assert!(query_result.is_err()); + assert!(result.is_err()); } #[test] @@ -322,14 +323,14 @@ fn account_key_addable_invalid() { let mut rng = rand::thread_rng(); let other_acc_key = random_account_key(&mut rng); - let query_result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { + let result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { rc.metered_add_gs( other_acc_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert_invalid_access(query_result, AccessRights::ADD); + assert_invalid_access(result, AccessRights::ADD); } #[test] @@ -338,10 +339,10 @@ fn contract_key_readable_valid() { // execution. let mut rng = rand::thread_rng(); let contract_key = random_contract_key(&mut rng); - let query_result = + let result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| rc.read_gs(&contract_key)); - assert!(query_result.is_ok()); + assert!(result.is_ok()); } #[test] @@ -350,14 +351,14 @@ fn contract_key_not_writeable() { // execution. let mut rng = rand::thread_rng(); let contract_key = random_contract_key(&mut rng); - let query_result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { + let result = build_runtime_context_and_execute(NamedKeys::new(), |mut rc| { rc.metered_write_gs( contract_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert_invalid_access(query_result, AccessRights::WRITE); + assert_invalid_access(result, AccessRights::WRITE); } #[test] @@ -367,7 +368,7 @@ fn contract_key_addable_valid() { let entity_hash = AddressableEntityHash::new([1u8; 32]); let (_account_key, entity_key, entity) = new_addressable_entity(account_hash, entity_hash); let authorization_keys = BTreeSet::from_iter(vec![account_hash]); - let mut address_generator = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut address_generator = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let mut rng = rand::thread_rng(); let contract_key = random_contract_key(&mut rng); @@ -414,21 +415,21 @@ fn contract_key_addable_valid() { contract_key, authorization_keys, access_rights, - EntityKind::SmartContract, account_hash, Rc::new(RefCell::new(address_generator)), Rc::clone(&tracking_copy), EngineConfig::default(), BlockTime::new(0), ProtocolVersion::V1_0_0, - DeployHash::from_raw(DEPLOY_HASH), + TransactionHash::V1(TransactionV1Hash::from_raw(TXN_HASH_RAW)), PHASE, RuntimeArgs::new(), Gas::new(U512::from(GAS_LIMIT)), Gas::default(), Vec::default(), U512::zero(), - EntryPointType::Session, + EntryPointType::Caller, + CallingAddContractVersion::Forbidden, ); assert!(runtime_context @@ -442,7 +443,7 @@ fn contract_key_addable_invalid() { let entity_hash = AddressableEntityHash::new([1u8; 32]); let (_, entity_key, entity) = new_addressable_entity(account_hash, entity_hash); let authorization_keys = BTreeSet::from_iter(vec![account_hash]); - let mut address_generator = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut address_generator = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let mut rng = rand::thread_rng(); let contract_key = random_contract_key(&mut rng); @@ -472,21 +473,21 @@ fn contract_key_addable_invalid() { other_contract_key, authorization_keys, access_rights, - EntityKind::Account(account_hash), account_hash, Rc::new(RefCell::new(address_generator)), Rc::clone(&tracking_copy), EngineConfig::default(), BlockTime::new(0), ProtocolVersion::V1_0_0, - DeployHash::from_raw(DEPLOY_HASH), + TransactionHash::V1(TransactionV1Hash::from_raw(TXN_HASH_RAW)), PHASE, RuntimeArgs::new(), Gas::new(U512::from(GAS_LIMIT)), Gas::default(), Vec::default(), U512::zero(), - EntryPointType::Session, + EntryPointType::Caller, + CallingAddContractVersion::Forbidden, ); let result = runtime_context.metered_add_gs(contract_key, named_uref_tuple); @@ -496,131 +497,117 @@ fn contract_key_addable_invalid() { #[test] fn uref_key_readable_valid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::READ); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = - build_runtime_context_and_execute(named_keys, |mut rc| rc.read_gs(&uref_key)); - assert!(query_result.is_ok()); + let result = build_runtime_context_and_execute(named_keys, |mut rc| rc.read_gs(&uref_key)); + assert!(result.is_ok()); } #[test] fn uref_key_readable_invalid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::WRITE); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = - build_runtime_context_and_execute(named_keys, |mut rc| rc.read_gs(&uref_key)); - assert_invalid_access(query_result, AccessRights::READ); + let result = build_runtime_context_and_execute(named_keys, |mut rc| rc.read_gs(&uref_key)); + assert_invalid_access(result, AccessRights::READ); } #[test] fn uref_key_writeable_valid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::WRITE); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { rc.metered_write_gs( uref_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert!(query_result.is_ok()); + assert!(result.is_ok()); } #[test] fn uref_key_writeable_invalid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::READ); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { rc.metered_write_gs( uref_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert_invalid_access(query_result, AccessRights::WRITE); + assert_invalid_access(result, AccessRights::WRITE); } #[test] fn uref_key_addable_valid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::ADD_WRITE); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { rc.metered_write_gs(uref_key, CLValue::from_t(10_i32).unwrap()) .expect("Writing to the GlobalState should work."); rc.metered_add_gs(uref_key, CLValue::from_t(1_i32).unwrap()) }); - assert!(query_result.is_ok()); + assert!(result.is_ok()); } #[test] fn uref_key_addable_invalid() { - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_key = create_uref_as_key(&mut rng, AccessRights::WRITE); let mut named_keys = NamedKeys::new(); named_keys.insert(String::new(), uref_key); - let query_result = build_runtime_context_and_execute(named_keys, |mut rc| { + let result = build_runtime_context_and_execute(named_keys, |mut rc| { rc.metered_add_gs( uref_key, StoredValue::CLValue(CLValue::from_t(1_i32).unwrap()), ) }); - assert_invalid_access(query_result, AccessRights::ADD); -} - -#[test] -fn hash_key_readable() { - // values under hash's are universally readable - let query = |runtime_context: RuntimeContext| { - let mut rng = rand::thread_rng(); - let key = random_hash(&mut rng); - runtime_context.validate_readable(&key) - }; - let query_result = build_runtime_context_and_execute(NamedKeys::new(), query); - assert!(query_result.is_ok()) + assert_invalid_access(result, AccessRights::ADD); } #[test] -fn hash_key_writeable() { +fn hash_key_is_not_writeable() { // values under hash's are immutable - let query = |runtime_context: RuntimeContext| { + let functor = |runtime_context: RuntimeContext| { let mut rng = rand::thread_rng(); let key = random_hash(&mut rng); runtime_context.validate_writeable(&key) }; - let query_result = build_runtime_context_and_execute(NamedKeys::new(), query); - assert!(query_result.is_err()) + let result = build_runtime_context_and_execute(NamedKeys::new(), functor); + assert!(result.is_err()) } #[test] -fn hash_key_addable_invalid() { +fn hash_key_is_not_addable() { // values under hashes are immutable - let query = |runtime_context: RuntimeContext| { + let functor = |runtime_context: RuntimeContext| { let mut rng = rand::thread_rng(); let key = random_hash(&mut rng); runtime_context.validate_addable(&key) }; - let query_result = build_runtime_context_and_execute(NamedKeys::new(), query); - assert!(query_result.is_err()) + let result = build_runtime_context_and_execute(NamedKeys::new(), functor); + assert!(result.is_err()) } #[test] @@ -628,7 +615,7 @@ fn manage_associated_keys() { // Testing a valid case only - successfully added a key, and successfully removed, // making sure `account_dirty` mutated let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { let account_hash = AccountHash::new([42; 32]); let weight = Weight::new(155); @@ -688,7 +675,7 @@ fn manage_associated_keys() { Ok(()) }; - let _ = build_runtime_context_and_execute(named_keys, query); + let _ = build_runtime_context_and_execute(named_keys, functor); } #[test] @@ -696,7 +683,7 @@ fn action_thresholds_management() { // Testing a valid case only - successfully added a key, and successfully removed, // making sure `account_dirty` mutated let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { let entity_hash_by_account_hash = CLValue::from_t(Key::Hash([2; 32])).expect("must convert to cl_value"); @@ -738,7 +725,7 @@ fn action_thresholds_management() { Ok(()) }; - let _ = build_runtime_context_and_execute(named_keys, query); + let _ = build_runtime_context_and_execute(named_keys, functor); } #[test] @@ -746,9 +733,10 @@ fn should_verify_ownership_before_adding_key() { // Testing a valid case only - successfully added a key, and successfully removed, // making sure `account_dirty` mutated let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { // Overwrites a `base_key` to a different one before doing any operation as // account `[0; 32]` + // TODO: this test should be updated to use v2.0.0 / AddressableEntity model let entity_hash_by_account_hash = CLValue::from_t(Key::Hash([2; 32])).expect("must convert to cl_value"); @@ -770,13 +758,17 @@ fn should_verify_ownership_before_adding_key() { .expect_err("This operation should return error"); match err { + ExecError::UnexpectedKeyVariant(_) => { + // This is the v2.0.0 error as this test is currently using Key::Hash + // instead of Key::AddressableEntity + } ExecError::AddKeyFailure(AddKeyFailure::PermissionDenied) => {} e => panic!("Invalid error variant: {:?}", e), } Ok(()) }; - let _ = build_runtime_context_and_execute(named_keys, query); + let _ = build_runtime_context_and_execute(named_keys, functor); } #[test] @@ -784,9 +776,10 @@ fn should_verify_ownership_before_removing_a_key() { // Testing a valid case only - successfully added a key, and successfully removed, // making sure `account_dirty` mutated let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { // Overwrites a `base_key` to a different one before doing any operation as // account `[0; 32]` + // TODO: this test should be updated to use v2.0.0 / AddressableEntity model runtime_context.entity_key = Key::Hash([1; 32]); let err = runtime_context @@ -794,13 +787,17 @@ fn should_verify_ownership_before_removing_a_key() { .expect_err("This operation should return error"); match err { + ExecError::UnexpectedKeyVariant(_) => { + // this is the v2.0 error because this test is currently using + // Key::Hash instead of Key::AddressableEntity + } ExecError::RemoveKeyFailure(RemoveKeyFailure::PermissionDenied) => {} ref e => panic!("Invalid error variant: {:?}", e), } Ok(()) }; - let _ = build_runtime_context_and_execute(named_keys, query); + let _ = build_runtime_context_and_execute(named_keys, functor); } #[test] @@ -808,9 +805,10 @@ fn should_verify_ownership_before_setting_action_threshold() { // Testing a valid case only - successfully added a key, and successfully removed, // making sure `account_dirty` mutated let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { // Overwrites a `base_key` to a different one before doing any operation as // account `[0; 32]` + // TODO: this test should be updated to v2.0.0 / AddressableEntityHash model runtime_context.entity_key = Key::Hash([1; 32]); let err = runtime_context @@ -818,39 +816,44 @@ fn should_verify_ownership_before_setting_action_threshold() { .expect_err("This operation should return error"); match err { + ExecError::UnexpectedKeyVariant(_) => { + // this is what is returned under protocol version 2.0 because Key::Hash(_) is + // deprecated. + } ExecError::SetThresholdFailure(SetThresholdFailure::PermissionDeniedError) => {} ref e => panic!("Invalid error variant: {:?}", e), } Ok(()) }; - let _ = build_runtime_context_and_execute(named_keys, query); + let _ = build_runtime_context_and_execute(named_keys, functor); } #[test] fn can_roundtrip_key_value_pairs() { let named_keys = NamedKeys::new(); - let query = |mut runtime_context: RuntimeContext| { + let functor = |mut runtime_context: RuntimeContext| { let deploy_hash = [1u8; 32]; let mut uref_address_generator = AddressGenerator::new(&deploy_hash, Phase::Session); let test_uref = create_uref_as_key(&mut uref_address_generator, AccessRights::default()) .as_uref() .cloned() .expect("must have created URef from the key"); - let test_value = CLValue::from_t("test_value".to_string()).unwrap(); + let expected = CLValue::from_t(U512::zero()).unwrap(); runtime_context - .write_purse_uref(test_uref.to_owned(), test_value.clone()) + .write_balance(test_uref.to_owned(), expected.clone()) .expect("should write_ls"); let result = runtime_context - .read_purse_uref(&test_uref) + .available_balance(&test_uref, HoldsEpoch::NOT_APPLICABLE) .expect("should read_ls"); - Ok(result == Some(test_value)) + let actual = CLValue::from_t(result.value()).unwrap(); + Ok(actual == expected) }; - let query_result = build_runtime_context_and_execute(named_keys, query).expect("should be ok"); - assert!(query_result) + let result = build_runtime_context_and_execute(named_keys, functor).expect("should be ok"); + assert!(result) } #[test] @@ -981,7 +984,7 @@ fn validate_valid_purse_of_an_account() { #[test] fn should_meter_for_gas_storage_write() { // Test fixture - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_as_key = create_uref_as_key(&mut rng, AccessRights::READ_WRITE); let mut named_keys = NamedKeys::new(); @@ -1016,7 +1019,7 @@ fn should_meter_for_gas_storage_write() { #[test] fn should_meter_for_gas_storage_add() { // Test fixture - let mut rng = AddressGenerator::new(&DEPLOY_HASH, PHASE); + let mut rng = AddressGenerator::new(&TXN_HASH_RAW, PHASE); let uref_as_key = create_uref_as_key(&mut rng, AccessRights::ADD_WRITE); let mut named_keys = NamedKeys::new(); diff --git a/execution_engine_testing/test_support/Cargo.toml b/execution_engine_testing/test_support/Cargo.toml index 23f021afe4..492ed70a82 100644 --- a/execution_engine_testing/test_support/Cargo.toml +++ b/execution_engine_testing/test_support/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/CasperLabs/casper-node/tree/master/execution_en license = "Apache-2.0" [dependencies] +blake2 = "0.9.0" casper-execution-engine = { version = "6.0.0", path = "../../execution_engine", features = ["test-support"] } casper-storage = { version = "1.4.3", path = "../../storage" } casper-types = { version = "3.0.0", path = "../../types" } diff --git a/execution_engine_testing/test_support/resources/chainspec.toml b/execution_engine_testing/test_support/resources/chainspec.toml index 18f4fbd206..8815ac74ee 120000 --- a/execution_engine_testing/test_support/resources/chainspec.toml +++ b/execution_engine_testing/test_support/resources/chainspec.toml @@ -1 +1 @@ -../../../resources/production/chainspec.toml \ No newline at end of file +../../../resources/local/chainspec.toml \ No newline at end of file diff --git a/execution_engine_testing/test_support/src/auction.rs b/execution_engine_testing/test_support/src/auction.rs deleted file mode 100644 index 3f0a48dcc8..0000000000 --- a/execution_engine_testing/test_support/src/auction.rs +++ /dev/null @@ -1,389 +0,0 @@ -use std::{collections::HashSet, convert::TryFrom, io::Write, time::Instant}; - -use lmdb::{Cursor, Transaction}; -use rand::Rng; -use tempfile::TempDir; - -use casper_execution_engine::engine_state::ExecuteRequest; -use casper_storage::{ - data_access_layer::{DataAccessLayer, GenesisRequest, TrieRequest}, - global_state::{ - state::{lmdb::LmdbGlobalState, StateProvider}, - trie::Trie, - }, -}; -use casper_types::{ - account::AccountHash, - bytesrepr::{self}, - global_state::Pointer, - runtime_args, - system::auction, - ChainspecRegistry, Digest, GenesisAccount, GenesisConfigBuilder, GenesisValidator, Key, Motes, - ProtocolVersion, PublicKey, SecretKey, StoredValue, DEFAULT_REFUND_HANDLING, U512, -}; - -use crate::{ - transfer, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, StepRequestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_ACCOUNT_PUBLIC_KEY, - DEFAULT_AUCTION_DELAY, DEFAULT_FEE_HANDLING, DEFAULT_GENESIS_CONFIG_HASH, - DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, - DEFAULT_PROPOSER_PUBLIC_KEY, DEFAULT_PROTOCOL_VERSION, DEFAULT_ROUND_SEIGNIORAGE_RATE, - DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY, DEFAULT_WASM_CONFIG, SYSTEM_ADDR, -}; - -const ARG_AMOUNT: &str = "amount"; -const ARG_TARGET: &str = "target"; -const ARG_ID: &str = "id"; - -const DELEGATION_RATE: u8 = 1; -const ID_NONE: Option = None; - -/// Initial balance for delegators in our test. -pub const DELEGATOR_INITIAL_BALANCE: u64 = 500 * 1_000_000_000u64; - -const VALIDATOR_BID_AMOUNT: u64 = 100; - -/// Amount of time to step foward between runs of the auction in our tests. -pub const TIMESTAMP_INCREMENT_MILLIS: u64 = 30_000; - -const TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE: u64 = 1_000_000 * 1_000_000_000; - -/// Run a block with transfers and optionally run step. -#[allow(clippy::too_many_arguments)] -pub fn run_blocks_with_transfers_and_step( - transfer_count: usize, - purse_count: usize, - use_scratch: bool, - run_auction: bool, - block_count: usize, - delegator_count: usize, - validator_count: usize, - mut report_writer: impl Write, -) { - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = LmdbWasmTestBuilder::new(data_dir.as_ref()); - let delegator_keys = generate_public_keys(delegator_count); - let validator_keys = generate_public_keys(validator_count); - let mut necessary_tries = HashSet::new(); - - run_genesis_and_create_initial_accounts( - &mut builder, - &validator_keys, - delegator_keys - .iter() - .map(|public_key| public_key.to_account_hash()) - .collect::>(), - U512::from(TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE), - ); - let contract_hash = builder.get_auction_contract_hash(); - let mut next_validator_iter = validator_keys.iter().cycle(); - - for delegator_public_key in delegator_keys { - let delegation_amount = U512::from(2000 * 1_000_000_000u64); - let delegator_account_hash = delegator_public_key.to_account_hash(); - let next_validator_key = next_validator_iter - .next() - .expect("should produce values forever"); - let delegate = create_delegate_request( - delegator_public_key, - next_validator_key.clone(), - delegation_amount, - delegator_account_hash, - contract_hash, - ); - builder.exec(delegate); - builder.expect_success(); - builder.commit(); - builder.clear_results(); - } - - let purse_amount = U512::from(1_000_000_000u64); - - let purses = transfer::create_test_purses( - &mut builder, - *DEFAULT_ACCOUNT_ADDR, - purse_count as u64, - purse_amount, - ); - - let exec_requests = transfer::create_multiple_native_transfers_to_purses( - *DEFAULT_ACCOUNT_ADDR, - transfer_count, - &purses, - ); - - let mut total_transfers = 0; - { - let data_access_layer = builder.data_access_layer(); - let lmdb_env = data_access_layer.state().environment().env(); - let db = data_access_layer.state().trie_store().get_db(); - - let txn = lmdb_env.begin_ro_txn().unwrap(); - let mut cursor = txn.open_ro_cursor(db).unwrap(); - - let existing_keys = cursor - .iter() - .map(Result::unwrap) - .map(|(key, _)| Digest::try_from(key).expect("should be a digest")); - necessary_tries.extend(existing_keys); - } - writeln!( - report_writer, - "height,db-size,transfers,time_ms,necessary_tries,total_tries" - ) - .unwrap(); - // simulating a block boundary here. - for current_block in 0..block_count { - let start = Instant::now(); - total_transfers += exec_requests.len(); - - transfer::transfer_to_account_multiple_native_transfers( - &mut builder, - &exec_requests, - use_scratch, - ); - let transfer_root = builder.get_post_state_hash(); - let maybe_auction_root = if run_auction { - if use_scratch { - step_and_run_auction(&mut builder); - } else { - builder.advance_era(); - builder.commit(); - } - Some(builder.get_post_state_hash()) - } else { - None - }; - let exec_time = start.elapsed(); - { - find_necessary_tries( - builder.data_access_layer(), - &mut necessary_tries, - transfer_root, - ); - } - - if let Some(auction_root) = maybe_auction_root { - find_necessary_tries( - builder.data_access_layer(), - &mut necessary_tries, - auction_root, - ); - } - - let total_tries = { - let data_access_layer = builder.data_access_layer(); - let lmdb_env = data_access_layer.state().environment().env(); - let db = data_access_layer.state().trie_store().get_db(); - let txn = lmdb_env.begin_ro_txn().unwrap(); - let mut cursor = txn.open_ro_cursor(db).unwrap(); - cursor.iter().count() - }; - - if use_scratch { - // This assertion is only valid with the scratch trie. - assert_eq!( - necessary_tries.len(), - total_tries, - "should not create unnecessary tries" - ); - } - - writeln!( - report_writer, - "{},{},{},{},{},{}", - current_block, - builder.lmdb_on_disk_size().unwrap(), - total_transfers, - exec_time.as_millis() as usize, - necessary_tries.len(), - total_tries, - ) - .unwrap(); - report_writer.flush().unwrap(); - } -} - -// find all necessary tries - hoist to FN -fn find_necessary_tries( - data_access_layer: &DataAccessLayer, - necessary_tries: &mut HashSet, - state_root: Digest, -) { - let mut queue = Vec::new(); - queue.push(state_root); - - while let Some(root) = queue.pop() { - if necessary_tries.contains(&root) { - continue; - } - necessary_tries.insert(root); - - let req = TrieRequest::new(root, None); - let trie_bytes = data_access_layer - .trie(req) - .into_legacy() - .unwrap() - .expect("trie should exist") - .into_inner(); - - if let Some(0) = trie_bytes.first() { - continue; - } - - let trie: Trie = - bytesrepr::deserialize(trie_bytes.inner_bytes().to_owned()) - .expect("unable to deserialize"); - - match trie { - Trie::Leaf { .. } => continue, - Trie::Node { pointer_block } => queue.extend(pointer_block.as_indexed_pointers().map( - |(_idx, ptr)| match ptr { - Pointer::LeafPointer(digest) | Pointer::NodePointer(digest) => digest, - }, - )), - Trie::Extension { affix: _, pointer } => match pointer { - Pointer::LeafPointer(digest) | Pointer::NodePointer(digest) => queue.push(digest), - }, - } - } -} - -/// Runs genesis, creates system, validator and delegator accounts, and funds the system account and -/// delegator accounts. -pub fn run_genesis_and_create_initial_accounts( - builder: &mut LmdbWasmTestBuilder, - validator_keys: &[PublicKey], - delegator_accounts: Vec, - delegator_initial_balance: U512, -) { - let mut genesis_accounts = vec![ - GenesisAccount::account( - DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::from(u128::MAX)), - None, - ), - GenesisAccount::account( - DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - None, - ), - ]; - for validator in validator_keys { - genesis_accounts.push(GenesisAccount::account( - validator.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), - Some(GenesisValidator::new( - Motes::new(U512::from(VALIDATOR_BID_AMOUNT)), - DELEGATION_RATE, - )), - )) - } - let run_genesis_request = - create_run_genesis_request(validator_keys.len() as u32 + 2, genesis_accounts); - builder.run_genesis(run_genesis_request); - - // Setup the system account with enough cspr - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => *SYSTEM_ADDR, - ARG_AMOUNT => U512::from(10_000 * 1_000_000_000u64), - ARG_ID => ID_NONE, - }, - ) - .build(); - builder.exec(transfer); - builder.expect_success().commit(); - - for (_i, delegator_account) in delegator_accounts.iter().enumerate() { - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => *delegator_account, - ARG_AMOUNT => delegator_initial_balance, - ARG_ID => ID_NONE, - }, - ) - .build(); - builder.exec(transfer); - builder.expect_success().commit(); - } -} - -fn create_run_genesis_request( - validator_slots: u32, - genesis_accounts: Vec, -) -> GenesisRequest { - let genesis_config = GenesisConfigBuilder::default() - .with_accounts(genesis_accounts) - .with_wasm_config(*DEFAULT_WASM_CONFIG) - .with_system_config(*DEFAULT_SYSTEM_CONFIG) - .with_validator_slots(validator_slots) - .with_auction_delay(DEFAULT_AUCTION_DELAY) - .with_locked_funds_period_millis(DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS) - .with_round_seigniorage_rate(DEFAULT_ROUND_SEIGNIORAGE_RATE) - .with_unbonding_delay(DEFAULT_UNBONDING_DELAY) - .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) - .with_refund_handling(DEFAULT_REFUND_HANDLING) - .with_fee_handling(DEFAULT_FEE_HANDLING) - .build(); - - GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, - genesis_config, - ChainspecRegistry::new_with_genesis(&[], &[]), - ) -} - -/// Creates a delegation request. -pub fn create_delegate_request( - delegator_public_key: PublicKey, - next_validator_key: PublicKey, - delegation_amount: U512, - delegator_account_hash: AccountHash, - contract_hash: casper_types::AddressableEntityHash, -) -> ExecuteRequest { - let entry_point = auction::METHOD_DELEGATE; - let args = runtime_args! { - auction::ARG_DELEGATOR => delegator_public_key, - auction::ARG_VALIDATOR => next_validator_key, - auction::ARG_AMOUNT => delegation_amount, - }; - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let deploy = DeployItemBuilder::new() - .with_address(delegator_account_hash) - .with_stored_session_hash(contract_hash, entry_point, args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => U512::from(2_500_000_000_u64) }) - .with_authorization_keys(&[delegator_account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() -} - -/// Generate `key_count` public keys. -pub fn generate_public_keys(key_count: usize) -> Vec { - let mut ret = Vec::with_capacity(key_count); - for _ in 0..key_count { - let bytes: [u8; SecretKey::ED25519_LENGTH] = rand::random(); - let secret_key = SecretKey::ed25519_from_bytes(bytes).unwrap(); - let public_key = PublicKey::from(&secret_key); - ret.push(public_key); - } - ret -} - -/// Build a step request and run the auction. -pub fn step_and_run_auction(builder: &mut LmdbWasmTestBuilder) { - let step_request_builder = StepRequestBuilder::new() - .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(ProtocolVersion::V1_0_0); - - let step_request = step_request_builder - .with_next_era_id(builder.get_era().successor()) - .build(); - builder.step_with_scratch(step_request); - builder.write_scratch_to_db(); -} diff --git a/execution_engine_testing/test_support/src/chainspec_config.rs b/execution_engine_testing/test_support/src/chainspec_config.rs index bd992f2ee7..5a17e99b78 100644 --- a/execution_engine_testing/test_support/src/chainspec_config.rs +++ b/execution_engine_testing/test_support/src/chainspec_config.rs @@ -12,8 +12,8 @@ use casper_execution_engine::engine_state::{EngineConfig, EngineConfigBuilder}; use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ system::auction::VESTING_SCHEDULE_LENGTH_MILLIS, CoreConfig, FeeHandling, GenesisAccount, - GenesisConfig, GenesisConfigBuilder, MintCosts, ProtocolVersion, RefundHandling, SystemConfig, - TimeDiff, WasmConfig, + GenesisConfig, GenesisConfigBuilder, MintCosts, PricingHandling, ProtocolVersion, + RefundHandling, SystemConfig, TimeDiff, WasmConfig, }; use crate::{ @@ -24,8 +24,8 @@ use crate::{ /// The name of the chainspec file on disk. pub const CHAINSPEC_NAME: &str = "chainspec.toml"; -/// Path to the production chainspec used in the Casper mainnet. -pub static PRODUCTION_PATH: Lazy = Lazy::new(|| { +/// Symlink to chainspec. +pub static CHAINSPEC_SYMLINK: Lazy = Lazy::new(|| { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("resources/") .join(CHAINSPEC_NAME) @@ -47,7 +47,7 @@ pub enum Error { /// This struct can be parsed from a TOML-encoded chainspec file. It means that as the /// chainspec format changes over versions, as long as we maintain the core config in this form /// in the chainspec file, it can continue to be parsed as an `ChainspecConfig`. -#[derive(Deserialize, Clone, Default)] +#[derive(Deserialize, Clone, Default, Debug)] pub struct ChainspecConfig { /// CoreConfig #[serde(rename = "core")] @@ -81,7 +81,8 @@ impl ChainspecConfig { ChainspecConfig::from_bytes(&bytes) } - pub(crate) fn from_chainspec_path>(filename: P) -> Result { + /// Load from path. + pub fn from_chainspec_path>(filename: P) -> Result { Self::from_path(filename) } @@ -105,14 +106,22 @@ impl ChainspecConfig { genesis_accounts: Vec, protocol_version: ProtocolVersion, ) -> Result { - let chainspec_config = ChainspecConfig::from_path(filename)?; + ChainspecConfig::from_path(filename)? + .create_genesis_request(genesis_accounts, protocol_version) + } + /// Create genesis request from self. + pub fn create_genesis_request( + &self, + genesis_accounts: Vec, + protocol_version: ProtocolVersion, + ) -> Result { // if you get a compilation error here, make sure to update the builder below accordingly let ChainspecConfig { core_config, wasm_config, system_costs_config, - } = chainspec_config; + } = self; let CoreConfig { validator_slots, auction_delay, @@ -124,31 +133,31 @@ impl ChainspecConfig { let genesis_config = GenesisConfigBuilder::new() .with_accounts(genesis_accounts) - .with_wasm_config(wasm_config) - .with_system_config(system_costs_config) - .with_validator_slots(validator_slots) - .with_auction_delay(auction_delay) + .with_wasm_config(*wasm_config) + .with_system_config(*system_costs_config) + .with_validator_slots(*validator_slots) + .with_auction_delay(*auction_delay) .with_locked_funds_period_millis(locked_funds_period.millis()) - .with_round_seigniorage_rate(round_seigniorage_rate) - .with_unbonding_delay(unbonding_delay) + .with_round_seigniorage_rate(*round_seigniorage_rate) + .with_unbonding_delay(*unbonding_delay) .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) .build(); Ok(GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_GENESIS_CONFIG_HASH, protocol_version, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), )) } - /// Create a `RunGenesisRequest` using values from the production `chainspec.toml`. - pub fn create_genesis_request_from_production_chainspec( + /// Create a `RunGenesisRequest` using values from the local `chainspec.toml`. + pub fn create_genesis_request_from_local_chainspec( genesis_accounts: Vec, protocol_version: ProtocolVersion, ) -> Result { Self::create_genesis_request_from_chainspec( - &*PRODUCTION_PATH, + &*CHAINSPEC_SYMLINK, genesis_accounts, protocol_version, ) @@ -208,6 +217,12 @@ impl ChainspecConfig { self } + /// Sets pricing handling config option. + pub fn with_pricing_handling(mut self, pricing_handling: PricingHandling) -> Self { + self.core_config.pricing_handling = pricing_handling; + self + } + /// Sets strict argument checking. pub fn with_strict_argument_checking(mut self, strict_argument_checking: bool) -> Self { self.core_config.strict_argument_checking = strict_argument_checking; diff --git a/execution_engine_testing/test_support/src/deploy_item_builder.rs b/execution_engine_testing/test_support/src/deploy_item_builder.rs index 258094afd2..78b619e26c 100644 --- a/execution_engine_testing/test_support/src/deploy_item_builder.rs +++ b/execution_engine_testing/test_support/src/deploy_item_builder.rs @@ -4,8 +4,8 @@ use rand::Rng; use casper_execution_engine::engine_state::deploy_item::DeployItem; use casper_types::{ - account::AccountHash, AddressableEntityHash, DeployHash, EntityVersion, ExecutableDeployItem, - HashAddr, PackageHash, RuntimeArgs, + account::AccountHash, bytesrepr::Bytes, AddressableEntityHash, DeployHash, EntityVersion, + ExecutableDeployItem, HashAddr, PackageHash, RuntimeArgs, }; use crate::{utils, DEFAULT_GAS_PRICE}; @@ -15,7 +15,7 @@ struct DeployItemData { pub address: Option, pub payment_code: Option, pub session_code: Option, - pub gas_price: u64, + pub gas_price: u8, pub authorization_keys: BTreeSet, pub deploy_hash: Option, } @@ -38,7 +38,11 @@ impl DeployItemBuilder { } /// Sets the payment bytes for the deploy. - pub fn with_payment_bytes(mut self, module_bytes: Vec, args: RuntimeArgs) -> Self { + pub fn with_payment_bytes>( + mut self, + module_bytes: T, + args: RuntimeArgs, + ) -> Self { self.deploy_item.payment_code = Some(ExecutableDeployItem::ModuleBytes { module_bytes: module_bytes.into(), args, @@ -47,13 +51,13 @@ impl DeployItemBuilder { } /// Sets the payment bytes of the deploy to an empty Vec. - pub fn with_empty_payment_bytes(self, args: RuntimeArgs) -> Self { + pub fn with_standard_payment(self, args: RuntimeArgs) -> Self { self.with_payment_bytes(vec![], args) } /// Sets the payment bytes of a deploy by reading a file and passing [`RuntimeArgs`]. pub fn with_payment_code>(self, file_name: T, args: RuntimeArgs) -> Self { - let module_bytes = utils::read_wasm_file_bytes(file_name); + let module_bytes = utils::read_wasm_file(file_name); self.with_payment_bytes(module_bytes, args) } @@ -120,7 +124,11 @@ impl DeployItemBuilder { } /// Sets the session bytes for the deploy. - pub fn with_session_bytes(mut self, module_bytes: Vec, args: RuntimeArgs) -> Self { + pub fn with_session_bytes>( + mut self, + module_bytes: T, + args: RuntimeArgs, + ) -> Self { self.deploy_item.session_code = Some(ExecutableDeployItem::ModuleBytes { module_bytes: module_bytes.into(), args, @@ -130,7 +138,7 @@ impl DeployItemBuilder { /// Sets the session code for the deploy using a wasm file. pub fn with_session_code>(self, file_name: T, args: RuntimeArgs) -> Self { - let module_bytes = utils::read_wasm_file_bytes(file_name); + let module_bytes = utils::read_wasm_file(file_name); self.with_session_bytes(module_bytes, args) } @@ -247,7 +255,7 @@ impl DeployItemBuilder { } /// Sets the gas price for the deploy. - pub fn with_gas_price(mut self, gas_price: u64) -> Self { + pub fn with_gas_price(mut self, gas_price: u8) -> Self { self.deploy_item.gas_price = gas_price; self } diff --git a/execution_engine_testing/test_support/src/execute_request_builder.rs b/execution_engine_testing/test_support/src/execute_request_builder.rs index 490e43dd14..3000a00852 100644 --- a/execution_engine_testing/test_support/src/execute_request_builder.rs +++ b/execution_engine_testing/test_support/src/execute_request_builder.rs @@ -1,161 +1,225 @@ -use std::convert::TryInto; - -use rand::Rng; +use std::collections::BTreeSet; use casper_execution_engine::engine_state::{ - deploy_item::DeployItem, execute_request::ExecuteRequest, + deploy_item::DeployItem, ExecutableItem, WasmV1Request, }; use casper_types::{ - account::AccountHash, runtime_args, AddressableEntityHash, EntityVersion, PackageHash, - ProtocolVersion, RuntimeArgs, + account::AccountHash, addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, + AddressableEntityHash, BlockTime, Digest, EntityVersion, Gas, InitiatorAddr, PackageHash, + Phase, RuntimeArgs, Transaction, TransactionHash, TransactionV1Hash, }; -use crate::{ - DeployItemBuilder, DEFAULT_BLOCK_TIME, DEFAULT_PAYMENT, DEFAULT_PROPOSER_PUBLIC_KEY, - DEFAULT_PROTOCOL_VERSION, -}; +use crate::{DeployItemBuilder, ARG_AMOUNT, DEFAULT_BLOCK_TIME, DEFAULT_PAYMENT}; -const ARG_AMOUNT: &str = "amount"; +/// A request comprising a [`WasmV1Request`] for use as session code, and an optional custom +/// payment `WasmV1Request`. +#[derive(Debug)] +pub struct ExecuteRequest { + /// The session request. + pub session: WasmV1Request, + /// The optional custom payment request. + pub custom_payment: Option, +} /// Builds an [`ExecuteRequest`]. #[derive(Debug)] pub struct ExecuteRequestBuilder { - execute_request: ExecuteRequest, + state_hash: Digest, + block_time: BlockTime, + transaction_hash: TransactionHash, + initiator_addr: InitiatorAddr, + payment: Option, + payment_gas_limit: Gas, + payment_entry_point: String, + payment_args: RuntimeArgs, + session: ExecutableItem, + session_gas_limit: Gas, + session_entry_point: String, + session_args: RuntimeArgs, + authorization_keys: BTreeSet, } impl ExecuteRequestBuilder { - /// Returns an [`ExecuteRequestBuilder`]. - pub fn new() -> Self { - Default::default() - } - - /// Takes a [`DeployItem`] and returns an [`ExecuteRequestBuilder`]. - pub fn from_deploy_item(deploy_item: DeployItem) -> Self { - ExecuteRequestBuilder::new().push_deploy(deploy_item) - } - - /// Adds a [`DeployItem`] to the [`ExecuteRequest`]. - pub fn push_deploy(mut self, deploy: DeployItem) -> Self { - self.execute_request.deploys.push(deploy); - self - } - - /// Sets the parent state hash of the [`ExecuteRequest`]. - pub fn with_pre_state_hash(mut self, pre_state_hash: &[u8]) -> Self { - self.execute_request.parent_state_hash = pre_state_hash.try_into().unwrap(); - self - } - - /// Sets the block time of the [`ExecuteRequest`]. - pub fn with_block_time(mut self, block_time: u64) -> Self { - self.execute_request.block_time = block_time; - self - } - - /// Sets the protocol version of the [`ExecuteRequest`]. - pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self { - self.execute_request.protocol_version = protocol_version; - self - } - - /// Sets the proposer used by the [`ExecuteRequest`]. - pub fn with_proposer(mut self, proposer: casper_types::PublicKey) -> Self { - self.execute_request.proposer = proposer; - self + /// The default value used for `WasmV1Request::state_hash`. + pub const DEFAULT_STATE_HASH: Digest = Digest::from_raw([1; 32]); + /// The default value used for `WasmV1Request::transaction_hash`. + pub const DEFAULT_TRANSACTION_HASH: TransactionHash = + TransactionHash::V1(TransactionV1Hash::from_raw([2; 32])); + /// The default value used for `WasmV1Request::entry_point`. + pub const DEFAULT_ENTRY_POINT: &'static str = "call"; + + /// Converts a `Transaction` into an `ExecuteRequestBuilder`. + pub fn from_transaction(txn: &Transaction) -> Self { + let authorization_keys = txn.authorization_keys(); + let session = WasmV1Request::new_session( + Self::DEFAULT_STATE_HASH, + BlockTime::new(DEFAULT_BLOCK_TIME), + Gas::new(5_000_000_000_000_u64), // TODO - set proper value + txn, + ) + .unwrap(); + + let payment: Option; + let payment_gas_limit: Gas; + let payment_entry_point: String; + let payment_args: RuntimeArgs; + if txn.is_standard_payment() { + payment = None; + payment_gas_limit = Gas::zero(); + payment_entry_point = DEFAULT_ENTRY_POINT_NAME.to_string(); + payment_args = RuntimeArgs::new(); + } else { + let request = WasmV1Request::new_custom_payment( + Self::DEFAULT_STATE_HASH, + BlockTime::new(DEFAULT_BLOCK_TIME), + Gas::new(5_000_000_000_000_u64), // TODO - set proper value + txn, + ) + .unwrap(); + payment = Some(request.executable_item); + payment_gas_limit = request.gas_limit; + payment_entry_point = request.entry_point; + payment_args = request.args; + } + + ExecuteRequestBuilder { + state_hash: session.state_hash, + block_time: session.block_time, + transaction_hash: session.transaction_hash, + initiator_addr: session.initiator_addr, + payment, + payment_gas_limit, + payment_entry_point, + payment_args, + session: session.executable_item, + session_gas_limit: session.gas_limit, + session_entry_point: session.entry_point, + session_args: session.args, + authorization_keys, + } } - /// Consumes self and returns an [`ExecuteRequest`]. - pub fn build(self) -> ExecuteRequest { - self.execute_request + /// Converts a `DeployItem` into an `ExecuteRequestBuilder`. + pub fn from_deploy_item(deploy_item: &DeployItem) -> Self { + let authorization_keys = deploy_item.authorization_keys.clone(); + let session = WasmV1Request::new_session_from_deploy_item( + Self::DEFAULT_STATE_HASH, + BlockTime::new(DEFAULT_BLOCK_TIME), + Gas::new(5_000_000_000_000_u64), // TODO - set proper value + deploy_item, + ) + .unwrap(); + + let payment: Option; + let payment_gas_limit: Gas; + let payment_entry_point: String; + let payment_args: RuntimeArgs; + if deploy_item.payment.is_standard_payment(Phase::Payment) { + payment = None; + payment_gas_limit = Gas::zero(); + payment_entry_point = DEFAULT_ENTRY_POINT_NAME.to_string(); + payment_args = RuntimeArgs::new(); + } else { + let request = WasmV1Request::new_custom_payment_from_deploy_item( + Self::DEFAULT_STATE_HASH, + BlockTime::new(DEFAULT_BLOCK_TIME), + Gas::new(5_000_000_000_000_u64), // TODO - set proper value + deploy_item, + ) + .unwrap(); + payment = Some(request.executable_item); + payment_gas_limit = request.gas_limit; + payment_entry_point = request.entry_point; + payment_args = request.args; + } + + ExecuteRequestBuilder { + state_hash: session.state_hash, + block_time: session.block_time, + transaction_hash: session.transaction_hash, + initiator_addr: session.initiator_addr, + payment, + payment_gas_limit, + payment_entry_point, + payment_args, + session: session.executable_item, + session_gas_limit: session.gas_limit, + session_entry_point: session.entry_point, + session_args: session.args, + authorization_keys, + } } - /// Returns an [`ExecuteRequest`] with standard dependencies. + /// Returns an [`ExecuteRequest`] derived from a deploy with standard dependencies. pub fn standard( account_hash: AccountHash, session_file: &str, session_args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash: [u8; 32] = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(account_hash) .with_session_code(session_file, session_args) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Returns an [`ExecuteRequest`] from a module bytes. + /// Returns an [`ExecuteRequest`] derived from a deploy with session module bytes. pub fn module_bytes( account_hash: AccountHash, module_bytes: Vec, session_args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash: [u8; 32] = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(account_hash) .with_session_bytes(module_bytes, session_args) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Returns an [`ExecuteRequest`] that will call a stored contract by hash. + /// Returns an [`ExecuteRequest`] derived from a deploy with a session item that will call a + /// stored contract by hash. pub fn contract_call_by_hash( sender: AccountHash, contract_hash: AddressableEntityHash, entry_point: &str, args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(sender) .with_stored_session_hash(contract_hash, entry_point, args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Returns an [`ExecuteRequest`] that will call a stored contract by named key. + /// Returns an [`ExecuteRequest`] derived from a deploy with a session item that will call a + /// stored contract by name. pub fn contract_call_by_name( sender: AccountHash, contract_name: &str, entry_point: &str, args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(sender) .with_stored_session_named_key(contract_name, entry_point, args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Returns an [`ExecuteRequest`] that will call a versioned stored contract by hash. + /// Returns an [`ExecuteRequest`] derived from a deploy with a session item that will call a + /// versioned stored contract by hash. pub fn versioned_contract_call_by_hash( sender: AccountHash, contract_package_hash: PackageHash, @@ -163,10 +227,7 @@ impl ExecuteRequestBuilder { entry_point_name: &str, args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(sender) .with_stored_versioned_contract_by_hash( contract_package_hash.value(), @@ -174,15 +235,14 @@ impl ExecuteRequestBuilder { entry_point_name, args, ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Calls a versioned contract from contract package hash key_name + /// Returns an [`ExecuteRequest`] derived from a deploy with a session item that will call a + /// versioned stored contract by name. pub fn versioned_contract_call_by_name( sender: AccountHash, contract_name: &str, @@ -190,69 +250,74 @@ impl ExecuteRequestBuilder { entry_point_name: &str, args: RuntimeArgs, ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(sender) .with_stored_versioned_contract_by_name(contract_name, version, entry_point_name, args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + Self::from_deploy_item(&deploy_item) } - /// Returns an [`ExecuteRequest`] for a native transfer. - pub fn transfer(sender: AccountHash, transfer_args: RuntimeArgs) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let deploy_item = DeployItemBuilder::new() - .with_address(sender) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(transfer_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::from_deploy_item(deploy_item) + /// Sets the block time of the [`WasmV1Request`]s. + pub fn with_block_time>(mut self, block_time: T) -> Self { + self.block_time = block_time.into(); + self } - /// Returns an [`ExecuteRequest`] with standard dependencies and a specified set of - /// associated keys. - pub fn with_authorization_keys( - account_hash: AccountHash, - session_file: &str, - session_args: RuntimeArgs, - authorization_keys: &[AccountHash], - ) -> Self { - let mut rng = rand::thread_rng(); - let deploy_hash: [u8; 32] = rng.gen(); - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, session_args) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(authorization_keys) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) + /// Sets the authorization keys used by the [`WasmV1Request`]s. + pub fn with_authorization_keys(mut self, authorization_keys: BTreeSet) -> Self { + self.authorization_keys = authorization_keys; + self } -} -impl Default for ExecuteRequestBuilder { - fn default() -> Self { - let execute_request = ExecuteRequest { - block_time: DEFAULT_BLOCK_TIME, - protocol_version: *DEFAULT_PROTOCOL_VERSION, - proposer: DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - ..Default::default() + /// Consumes self and returns an `ExecuteRequest`. + pub fn build(self) -> ExecuteRequest { + let ExecuteRequestBuilder { + state_hash, + block_time, + transaction_hash, + initiator_addr, + payment, + payment_gas_limit, + payment_entry_point, + payment_args, + session, + session_gas_limit, + session_entry_point, + session_args, + authorization_keys, + } = self; + + let maybe_custom_payment = payment.map(|executable_item| WasmV1Request { + state_hash, + block_time, + transaction_hash, + gas_limit: payment_gas_limit, + initiator_addr: initiator_addr.clone(), + executable_item, + entry_point: payment_entry_point, + args: payment_args, + authorization_keys: authorization_keys.clone(), + phase: Phase::Payment, + }); + + let session = WasmV1Request { + state_hash, + block_time, + transaction_hash, + gas_limit: session_gas_limit, + initiator_addr, + executable_item: session, + entry_point: session_entry_point, + args: session_args, + authorization_keys, + phase: Phase::Session, }; - ExecuteRequestBuilder { execute_request } + + ExecuteRequest { + session, + custom_payment: maybe_custom_payment, + } } } diff --git a/execution_engine_testing/test_support/src/lib.rs b/execution_engine_testing/test_support/src/lib.rs index 3f992c93db..fd90f4dcd1 100644 --- a/execution_engine_testing/test_support/src/lib.rs +++ b/execution_engine_testing/test_support/src/lib.rs @@ -9,15 +9,11 @@ #![warn(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -/// Utility methods for running the auction in a test or bench context. -pub mod auction; mod chainspec_config; mod deploy_item_builder; mod execute_request_builder; mod step_request_builder; - -/// Utilities for running transfers in a test or bench context. -pub mod transfer; +mod transfer_request_builder; mod upgrade_request_builder; pub mod utils; mod wasm_test_builder; @@ -27,16 +23,16 @@ use once_cell::sync::Lazy; use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ - account::AccountHash, ChainspecRegistry, Digest, GenesisAccount, GenesisConfig, - GenesisConfigBuilder, Motes, ProtocolVersion, PublicKey, SecretKey, SystemConfig, WasmConfig, - DEFAULT_FEE_HANDLING, DEFAULT_REFUND_HANDLING, U512, + account::AccountHash, testing::TestRng, ChainspecRegistry, Digest, GenesisAccount, + GenesisConfig, GenesisConfigBuilder, Motes, ProtocolVersion, PublicKey, SecretKey, + SystemConfig, WasmConfig, U512, }; -pub use chainspec_config::ChainspecConfig; -use chainspec_config::PRODUCTION_PATH; +pub use chainspec_config::{ChainspecConfig, CHAINSPEC_SYMLINK}; pub use deploy_item_builder::DeployItemBuilder; -pub use execute_request_builder::ExecuteRequestBuilder; +pub use execute_request_builder::{ExecuteRequest, ExecuteRequestBuilder}; pub use step_request_builder::StepRequestBuilder; +pub use transfer_request_builder::TransferRequestBuilder; pub use upgrade_request_builder::UpgradeRequestBuilder; pub use wasm_test_builder::{EntityWithNamedKeys, LmdbWasmTestBuilder, WasmTestBuilder}; @@ -59,7 +55,7 @@ pub const DEFAULT_UNBONDING_DELAY: u64 = 7; /// Ticks per year: 31536000000 /// /// (1+0.08)^((2^14)/31536000000)-1 is expressed as a fractional number below. -pub const DEFAULT_ROUND_SEIGNIORAGE_RATE: Ratio = Ratio::new_raw(7, 175070816); +pub const DEFAULT_ROUND_SEIGNIORAGE_RATE: Ratio = Ratio::new_raw(1, 4200000000000000000); /// Default chain name. pub const DEFAULT_CHAIN_NAME: &str = "casper-execution-engine-testing"; @@ -68,7 +64,7 @@ pub const DEFAULT_GENESIS_TIMESTAMP_MILLIS: u64 = 0; /// Default block time. pub const DEFAULT_BLOCK_TIME: u64 = 0; /// Default gas price. -pub const DEFAULT_GAS_PRICE: u64 = 1; +pub const DEFAULT_GAS_PRICE: u8 = 1; /// Amount named argument. pub const ARG_AMOUNT: &str = "amount"; /// Timestamp increment in milliseconds. @@ -83,14 +79,15 @@ pub const DEFAULT_MAX_QUERY_DEPTH: u64 = 5; pub const DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT: u32 = 12; /// Default value for minimum delegation amount in motes. pub const DEFAULT_MINIMUM_DELEGATION_AMOUNT: u64 = 500 * 1_000_000_000; - /// Default genesis config hash. -pub static DEFAULT_GENESIS_CONFIG_HASH: Lazy = Lazy::new(|| [42; 32].into()); +pub const DEFAULT_GENESIS_CONFIG_HASH: Digest = Digest::from_raw([42; 32]); + +/// Default account secret key. +pub static DEFAULT_ACCOUNT_SECRET_KEY: Lazy = + Lazy::new(|| SecretKey::ed25519_from_bytes([199; SecretKey::ED25519_LENGTH]).unwrap()); /// Default account public key. -pub static DEFAULT_ACCOUNT_PUBLIC_KEY: Lazy = Lazy::new(|| { - let secret_key = SecretKey::ed25519_from_bytes([199; SecretKey::ED25519_LENGTH]).unwrap(); - PublicKey::from(&secret_key) -}); +pub static DEFAULT_ACCOUNT_PUBLIC_KEY: Lazy = + Lazy::new(|| PublicKey::from(&*DEFAULT_ACCOUNT_SECRET_KEY)); /// Default test account address. pub static DEFAULT_ACCOUNT_ADDR: Lazy = Lazy::new(|| AccountHash::from(&*DEFAULT_ACCOUNT_PUBLIC_KEY)); @@ -99,9 +96,9 @@ pub static DEFAULT_ACCOUNT_ADDR: Lazy = pub static DEFAULT_ACCOUNT_KEY: Lazy = Lazy::new(|| AccountHash::from(&*DEFAULT_ACCOUNT_PUBLIC_KEY)); /// Default initial balance of a test account in motes. -pub const DEFAULT_ACCOUNT_INITIAL_BALANCE: u64 = 100_000_000_000_000_000u64; +pub const DEFAULT_ACCOUNT_INITIAL_BALANCE: u64 = 10_000_000_000_000_000_000_u64; /// Minimal amount for a transfer that creates new accounts. -pub const MINIMUM_ACCOUNT_CREATION_BALANCE: u64 = 7_500_000_000_000_000u64; +pub const MINIMUM_ACCOUNT_CREATION_BALANCE: u64 = 7_500_000_000_000_000_u64; /// Default proposer public key. pub static DEFAULT_PROPOSER_PUBLIC_KEY: Lazy = Lazy::new(|| { let secret_key = SecretKey::ed25519_from_bytes([198; SecretKey::ED25519_LENGTH]).unwrap(); @@ -115,20 +112,29 @@ pub static DEFAULT_ACCOUNTS: Lazy> = Lazy::new(|| { let mut ret = Vec::new(); let genesis_account = GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); ret.push(genesis_account); let proposer_account = GenesisAccount::account( DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); ret.push(proposer_account); + let rng = &mut TestRng::new(); + for _ in 0..10 { + let filler_account = GenesisAccount::account( + PublicKey::random(rng), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), + None, + ); + ret.push(filler_account); + } ret }); /// Default [`ProtocolVersion`]. -pub static DEFAULT_PROTOCOL_VERSION: Lazy = Lazy::new(|| ProtocolVersion::V2_0_0); +pub const DEFAULT_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V2_0_0; /// Default payment. pub static DEFAULT_PAYMENT: Lazy = Lazy::new(|| U512::from(1_500_000_000_000u64)); /// Default [`WasmConfig`]. @@ -148,8 +154,6 @@ pub static DEFAULT_EXEC_CONFIG: Lazy = Lazy::new(|| { .with_round_seigniorage_rate(DEFAULT_ROUND_SEIGNIORAGE_RATE) .with_unbonding_delay(DEFAULT_UNBONDING_DELAY) .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) - .with_refund_handling(DEFAULT_REFUND_HANDLING) - .with_fee_handling(DEFAULT_FEE_HANDLING) .build() }); @@ -158,16 +162,16 @@ pub static DEFAULT_CHAINSPEC_REGISTRY: Lazy = Lazy::new(|| ChainspecRegistry::new_with_genesis(&[1, 2, 3], &[4, 5, 6])); /// A [`GenesisRequest`] using cost tables matching those used in Casper Mainnet. -pub static PRODUCTION_RUN_GENESIS_REQUEST: Lazy = Lazy::new(|| { - ChainspecConfig::create_genesis_request_from_production_chainspec( +pub static LOCAL_GENESIS_REQUEST: Lazy = Lazy::new(|| { + ChainspecConfig::create_genesis_request_from_local_chainspec( DEFAULT_ACCOUNTS.clone(), - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_PROTOCOL_VERSION, ) .expect("must create the request") }); /// Round seigniorage rate from the production chainspec. pub static PRODUCTION_ROUND_SEIGNIORAGE_RATE: Lazy> = Lazy::new(|| { - let chainspec = ChainspecConfig::from_chainspec_path(&*PRODUCTION_PATH) + let chainspec = ChainspecConfig::from_chainspec_path(&*CHAINSPEC_SYMLINK) .expect("must create chainspec_config"); chainspec.core_config.round_seigniorage_rate }); @@ -180,7 +184,7 @@ mod tests { #[test] fn defaults_should_match_production_chainspec_values() { - let production = ChainspecConfig::from_chainspec_path(&*PRODUCTION_PATH).unwrap(); + let production = ChainspecConfig::from_chainspec_path(&*CHAINSPEC_SYMLINK).unwrap(); // No need to test `CoreConfig::validator_slots`. assert_eq!(production.core_config.auction_delay, DEFAULT_AUCTION_DELAY); assert_eq!( diff --git a/execution_engine_testing/test_support/src/transfer.rs b/execution_engine_testing/test_support/src/transfer.rs deleted file mode 100644 index a7eb234f6c..0000000000 --- a/execution_engine_testing/test_support/src/transfer.rs +++ /dev/null @@ -1,282 +0,0 @@ -use casper_execution_engine::engine_state::ExecuteRequest; -use casper_storage::global_state::state::{CommitProvider, ScratchProvider}; -use casper_types::{account::AccountHash, runtime_args, Key, URef, U512}; - -use crate::{ - DeployItemBuilder, ExecuteRequestBuilder, WasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, -}; - -const CONTRACT_CREATE_ACCOUNTS: &str = "create_accounts.wasm"; -const CONTRACT_CREATE_PURSES: &str = "create_purses.wasm"; -const CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT: &str = "transfer_to_existing_account.wasm"; -const CONTRACT_TRANSFER_TO_PURSE: &str = "transfer_to_purse.wasm"; - -/// Size of batch used in multiple execs benchmark, and multiple deploys per exec cases. -pub const TRANSFER_BATCH_SIZE: u64 = 3; - -/// Test target address. -pub const TARGET_ADDR: AccountHash = AccountHash::new([127; 32]); - -const ARG_AMOUNT: &str = "amount"; -const ARG_ID: &str = "id"; -const ARG_ACCOUNTS: &str = "accounts"; -const ARG_SEED_AMOUNT: &str = "seed_amount"; -const ARG_TOTAL_PURSES: &str = "total_purses"; -const ARG_TARGET: &str = "target"; -const ARG_TARGET_PURSE: &str = "target_purse"; - -/// Test value for number of deploys to generate for a block. -pub const BLOCK_TRANSFER_COUNT: usize = 2500; - -/// Converts an integer into an array of type [u8; 32] by converting integer -/// into its big endian representation and embedding it at the end of the -/// range. -fn make_deploy_hash(i: u64) -> [u8; 32] { - let mut result = [128; 32]; - result[32 - 8..].copy_from_slice(&i.to_be_bytes()); - result -} - -/// Create initial accounts and run genesis. -pub fn create_initial_accounts_and_run_genesis( - builder: &mut WasmTestBuilder, - accounts: Vec, - amount: U512, -) { - let exec_request = create_accounts_request(accounts, amount); - builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) - .exec(exec_request) - .expect_success() - .commit(); -} - -/// Creates a request that will call the create_accounts.wasm and create test accounts using the -/// default account for the initial transfer. -pub fn create_accounts_request(source_accounts: Vec, amount: U512) -> ExecuteRequest { - ExecuteRequestBuilder::standard( - *DEFAULT_ACCOUNT_ADDR, - CONTRACT_CREATE_ACCOUNTS, - runtime_args! { ARG_ACCOUNTS => source_accounts, ARG_SEED_AMOUNT => amount }, - ) - .build() -} - -/// Create a number of test purses with an initial balance. -pub fn create_test_purses( - builder: &mut WasmTestBuilder, - source: AccountHash, - total_purses: u64, - purse_amount: U512, -) -> Vec { - let exec_request = ExecuteRequestBuilder::standard( - source, - CONTRACT_CREATE_PURSES, - runtime_args! { - ARG_AMOUNT => U512::from(total_purses) * purse_amount, - ARG_TOTAL_PURSES => total_purses, - ARG_SEED_AMOUNT => purse_amount - }, - ) - .build(); - - builder.exec(exec_request).expect_success().commit(); - - // Return creates purses for given account by filtering named keys - let named_keys = builder.get_named_keys_by_account_hash(source); - - (0..total_purses) - .map(|index| { - let purse_lookup_key = format!("purse:{}", index); - let purse_uref = named_keys - .get(&purse_lookup_key) - .and_then(Key::as_uref) - .unwrap_or_else(|| panic!("should get named key {} as uref", purse_lookup_key)); - *purse_uref - }) - .collect() -} - -/// Uses multiple exec requests with a single deploy to transfer tokens. Executes all transfers in -/// batch determined by value of TRANSFER_BATCH_SIZE. -pub fn transfer_to_account_multiple_execs( - builder: &mut WasmTestBuilder, - account: AccountHash, - should_commit: bool, -) { - let amount = U512::one(); - - for _ in 0..TRANSFER_BATCH_SIZE { - let exec_request = ExecuteRequestBuilder::standard( - *DEFAULT_ACCOUNT_ADDR, - CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT, - runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => amount, - }, - ) - .build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } - } -} - -/// Executes multiple deploys per single exec with based on TRANSFER_BATCH_SIZE. -pub fn transfer_to_account_multiple_deploys( - builder: &mut WasmTestBuilder, - account: AccountHash, - should_commit: bool, -) { - let mut exec_builder = ExecuteRequestBuilder::new(); - - for i in 0..TRANSFER_BATCH_SIZE { - let deploy = DeployItemBuilder::default() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) - .with_session_code( - CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT, - runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => U512::one(), - }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash(make_deploy_hash(i)) // deploy_hash - .build(); - exec_builder = exec_builder.push_deploy(deploy); - } - - let exec_request = exec_builder.build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } -} - -/// Uses multiple exec requests with a single deploy to transfer tokens from purse to purse. -/// Executes all transfers in batch determined by value of TRANSFER_BATCH_SIZE. -pub fn transfer_to_purse_multiple_execs( - builder: &mut WasmTestBuilder, - purse: URef, - should_commit: bool, -) { - let amount = U512::one(); - - for _ in 0..TRANSFER_BATCH_SIZE { - let exec_request = ExecuteRequestBuilder::standard( - TARGET_ADDR, - CONTRACT_TRANSFER_TO_PURSE, - runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => amount }, - ) - .build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } - } -} - -/// Executes multiple deploys per single exec with based on TRANSFER_BATCH_SIZE. -pub fn transfer_to_purse_multiple_deploys( - builder: &mut WasmTestBuilder, - purse: URef, - should_commit: bool, -) { - let mut exec_builder = ExecuteRequestBuilder::new(); - - for i in 0..TRANSFER_BATCH_SIZE { - let deploy = DeployItemBuilder::default() - .with_address(TARGET_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - CONTRACT_TRANSFER_TO_PURSE, - runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => U512::one() }, - ) - .with_authorization_keys(&[TARGET_ADDR]) - .with_deploy_hash(make_deploy_hash(i)) // deploy_hash - .build(); - exec_builder = exec_builder.push_deploy(deploy); - } - - let exec_request = exec_builder.build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } -} - -/// This test simulates flushing at the end of a block. -pub fn transfer_to_account_multiple_native_transfers( - builder: &mut WasmTestBuilder, - execute_requests: &[ExecuteRequest], - use_scratch: bool, -) { - for exec_request in execute_requests { - let request = ExecuteRequest::new( - exec_request.parent_state_hash, - exec_request.block_time, - exec_request.deploys.clone(), - exec_request.protocol_version, - exec_request.proposer.clone(), - ); - if use_scratch { - builder.scratch_exec_and_commit(request).expect_success(); - } else { - builder.exec(request).expect_success(); - builder.commit(); - } - } - if use_scratch { - builder.write_scratch_to_db(); - } - // flush to disk only after entire block (simulates manual_sync_enabled=true config entry) - builder.flush_environment(); - - // WasmTestBuilder holds on to all execution results. This needs to be cleared to reduce - // overhead in this test - it will likely OOM without. - builder.clear_results(); -} - -/// Generate many native transfers from target_account. -pub fn create_multiple_native_transfers_to_purses( - source_account: AccountHash, - transfer_count: usize, - purses: &[URef], -) -> Vec { - let mut purse_index = 0usize; - let mut exec_requests = Vec::with_capacity(transfer_count); - for _ in 0..transfer_count { - let account = { - let account = purses[purse_index]; - if purse_index == purses.len() - 1 { - purse_index = 0; - } else { - purse_index += 1; - } - account - }; - let mut exec_builder = ExecuteRequestBuilder::new(); - let runtime_args = runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => U512::one(), - ARG_ID => >::None - }; - let native_transfer = DeployItemBuilder::new() - .with_address(source_account) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[source_account]) - .build(); - exec_builder = exec_builder.push_deploy(native_transfer); - let exec_request = exec_builder.build(); - exec_requests.push(exec_request); - } - exec_requests -} diff --git a/execution_engine_testing/test_support/src/transfer_request_builder.rs b/execution_engine_testing/test_support/src/transfer_request_builder.rs new file mode 100644 index 0000000000..7656a37957 --- /dev/null +++ b/execution_engine_testing/test_support/src/transfer_request_builder.rs @@ -0,0 +1,235 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + iter, +}; + +use blake2::{ + digest::{Update, VariableOutput}, + VarBlake2b, +}; +use num_rational::Ratio; + +use casper_storage::{ + data_access_layer::TransferRequest, + system::runtime_native::{Config as NativeRuntimeConfig, TransferConfig}, +}; +use casper_types::{ + account::AccountHash, + bytesrepr::ToBytes, + system::mint::{ARG_AMOUNT, ARG_ID, ARG_SOURCE, ARG_TARGET}, + BlockTime, CLValue, Digest, FeeHandling, Gas, HoldsEpoch, InitiatorAddr, ProtocolVersion, + RefundHandling, RuntimeArgs, TransactionHash, TransactionV1Hash, TransferTarget, URef, + DEFAULT_BALANCE_HOLD_INTERVAL, U512, +}; + +use crate::{ + DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_BLOCK_TIME, DEFAULT_PROTOCOL_VERSION, +}; + +/// Builds a [`TransferRequest`]. +#[derive(Debug)] +pub struct TransferRequestBuilder { + config: NativeRuntimeConfig, + state_hash: Digest, + block_time: BlockTime, + protocol_version: ProtocolVersion, + transaction_hash: Option, + initiator: InitiatorAddr, + authorization_keys: BTreeSet, + args: BTreeMap, + gas: Gas, +} + +impl TransferRequestBuilder { + /// The default value used for `TransferRequest::config`. + pub const DEFAULT_CONFIG: NativeRuntimeConfig = NativeRuntimeConfig::new( + TransferConfig::Unadministered, + FeeHandling::PayToProposer, + RefundHandling::Refund { + refund_ratio: Ratio::new_raw(99, 100), + }, + 0, + true, + true, + 0, + 500_000_000_000, + DEFAULT_BALANCE_HOLD_INTERVAL.millis(), + ); + /// The default value used for `TransferRequest::state_hash`. + pub const DEFAULT_STATE_HASH: Digest = Digest::from_raw([1; 32]); + /// The default value used for `TransferRequest::gas`. + pub const DEFAULT_GAS: u64 = 2_500_000_000; + + /// Constructs a new `TransferRequestBuilder`. + pub fn new, T: Into>(amount: A, target: T) -> Self { + let mut args = BTreeMap::new(); + let _ = args.insert( + ARG_AMOUNT.to_string(), + CLValue::from_t(amount.into()).unwrap(), + ); + let _ = args.insert( + ARG_ID.to_string(), + CLValue::from_t(Option::::None).unwrap(), + ); + let target_value = match target.into() { + TransferTarget::PublicKey(public_key) => CLValue::from_t(public_key), + TransferTarget::AccountHash(account_hash) => CLValue::from_t(account_hash), + TransferTarget::URef(uref) => CLValue::from_t(uref), + } + .unwrap(); + let _ = args.insert(ARG_TARGET.to_string(), target_value); + TransferRequestBuilder { + config: Self::DEFAULT_CONFIG, + state_hash: Self::DEFAULT_STATE_HASH, + block_time: BlockTime::new(DEFAULT_BLOCK_TIME), + protocol_version: DEFAULT_PROTOCOL_VERSION, + transaction_hash: None, + initiator: InitiatorAddr::PublicKey(DEFAULT_ACCOUNT_PUBLIC_KEY.clone()), + authorization_keys: iter::once(*DEFAULT_ACCOUNT_ADDR).collect(), + args, + gas: Gas::new(Self::DEFAULT_GAS), + } + } + + /// Sets the native runtime config of the [`TransferRequest`]. + pub fn with_native_runtime_config(mut self, config: NativeRuntimeConfig) -> Self { + self.config = config; + self + } + + /// Sets the block time of the [`TransferRequest`]. + pub fn with_block_time(mut self, block_time: u64) -> Self { + self.block_time = BlockTime::new(block_time); + self + } + + /// Sets the protocol version used by the [`TransferRequest`]. + pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self { + self.protocol_version = protocol_version; + self + } + + /// Sets the transaction hash used by the [`TransferRequest`]. + pub fn with_transaction_hash(mut self, transaction_hash: TransactionHash) -> Self { + self.transaction_hash = Some(transaction_hash); + self + } + + /// Sets the initiator used by the [`TransferRequest`], and adds its account hash to the set of + /// authorization keys. + pub fn with_initiator>(mut self, initiator: T) -> Self { + self.initiator = initiator.into(); + let _ = self + .authorization_keys + .insert(self.initiator.account_hash()); + self + } + + /// Sets the authorization keys used by the [`TransferRequest`]. + pub fn with_authorization_keys>( + mut self, + authorization_keys: T, + ) -> Self { + self.authorization_keys = authorization_keys.into_iter().collect(); + self + } + + /// Adds the "source" runtime arg, replacing the existing one if it exists. + pub fn with_source(mut self, source: URef) -> Self { + let value = CLValue::from_t(source).unwrap(); + let _ = self.args.insert(ARG_SOURCE.to_string(), value); + self + } + + /// Adds the "id" runtime arg, replacing the existing one if it exists.. + pub fn with_transfer_id(mut self, id: u64) -> Self { + let value = CLValue::from_t(Some(id)).unwrap(); + let _ = self.args.insert(ARG_ID.to_string(), value); + self + } + + /// Consumes self and returns a `TransferRequest`. + /// + /// If a transaction hash was not provided, the blake2b hash of the contents of the other fields + /// will be calculated, so that different requests will have different transaction hashes. Note + /// that this generated hash is not the same as what would have been generated on an actual + /// `Transaction` for an equivalent request. + pub fn build(self) -> TransferRequest { + let holds_epoch = + HoldsEpoch::from_millis(self.block_time.value(), self.config.balance_hold_interval()); + + let txn_hash = match self.transaction_hash { + Some(txn_hash) => txn_hash, + None => { + let mut result = [0; 32]; + let mut hasher = VarBlake2b::new(32).unwrap(); + + match &self.config.transfer_config() { + TransferConfig::Administered { + administrative_accounts, + allow_unrestricted_transfers, + } => hasher.update( + (administrative_accounts, allow_unrestricted_transfers) + .to_bytes() + .unwrap(), + ), + TransferConfig::Unadministered => { + hasher.update([1]); + } + } + hasher.update(self.config.fee_handling().to_bytes().unwrap()); + hasher.update(self.config.refund_handling().to_bytes().unwrap()); + hasher.update( + self.config + .vesting_schedule_period_millis() + .to_bytes() + .unwrap(), + ); + hasher.update(self.config.allow_auction_bids().to_bytes().unwrap()); + hasher.update(self.config.compute_rewards().to_bytes().unwrap()); + hasher.update( + self.config + .max_delegators_per_validator() + .to_bytes() + .unwrap(), + ); + hasher.update(self.config.minimum_delegation_amount().to_bytes().unwrap()); + hasher.update(self.state_hash); + hasher.update(self.block_time.to_bytes().unwrap()); + hasher.update(self.protocol_version.to_bytes().unwrap()); + hasher.update(self.initiator.to_bytes().unwrap()); + hasher.update(self.authorization_keys.to_bytes().unwrap()); + hasher.update(self.args.to_bytes().unwrap()); + hasher.update(self.gas.to_bytes().unwrap()); + hasher.finalize_variable(|slice| { + result.copy_from_slice(slice); + }); + TransactionHash::V1(TransactionV1Hash::from_raw(result)) + } + }; + + TransferRequest::with_runtime_args( + self.config, + self.state_hash, + holds_epoch, + self.protocol_version, + txn_hash, + self.initiator, + self.authorization_keys, + RuntimeArgs::from(self.args), + ) + } + + /// Sets the runtime args used by the [`TransferRequest`]. + /// + /// NOTE: This is not generally useful for creating a valid `TransferRequest`, and hence is + /// subject to change or deletion without notice. + #[doc(hidden)] + pub fn with_args(mut self, args: RuntimeArgs) -> Self { + self.args = args + .named_args() + .map(|named_arg| (named_arg.name().to_string(), named_arg.cl_value().clone())) + .collect(); + self + } +} diff --git a/execution_engine_testing/test_support/src/utils.rs b/execution_engine_testing/test_support/src/utils.rs index e8316cab9f..87b6031e43 100644 --- a/execution_engine_testing/test_support/src/utils.rs +++ b/execution_engine_testing/test_support/src/utils.rs @@ -3,17 +3,13 @@ use std::{ env, fs, path::{Path, PathBuf}, - rc::Rc, }; use once_cell::sync::Lazy; -use casper_execution_engine::engine_state::{execution_result::ExecutionResult, Error}; +use casper_execution_engine::engine_state::{Error, WasmV1Result}; use casper_storage::data_access_layer::GenesisRequest; -use casper_types::{ - Gas, GenesisAccount, GenesisConfig, GenesisConfigBuilder, DEFAULT_FEE_HANDLING, - DEFAULT_REFUND_HANDLING, -}; +use casper_types::{bytesrepr::Bytes, GenesisAccount, GenesisConfig, GenesisConfigBuilder}; use super::{DEFAULT_ROUND_SEIGNIORAGE_RATE, DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY}; use crate::{ @@ -97,7 +93,7 @@ fn get_compiled_wasm_paths() -> Vec { } /// Reads a given compiled contract file based on path -pub fn read_wasm_file_bytes>(contract_file: T) -> Vec { +pub fn read_wasm_file>(contract_file: T) -> Bytes { let mut attempted_paths = vec![]; if contract_file.as_ref().is_relative() { @@ -106,7 +102,7 @@ pub fn read_wasm_file_bytes>(contract_file: T) -> Vec { let mut filename = wasm_path.clone(); filename.push(contract_file.as_ref()); if let Ok(wasm_bytes) = fs::read(&filename) { - return wasm_bytes; + return Bytes::from(wasm_bytes); } attempted_paths.push(filename); } @@ -114,7 +110,7 @@ pub fn read_wasm_file_bytes>(contract_file: T) -> Vec { // Try just opening in case the arg is a valid path relative to current working dir, or is a // valid absolute path. if let Ok(wasm_bytes) = fs::read(contract_file.as_ref()) { - return wasm_bytes; + return Bytes::from(wasm_bytes); } attempted_paths.push(contract_file.as_ref().to_owned()); @@ -137,8 +133,6 @@ pub fn create_genesis_config(accounts: Vec) -> GenesisConfig { let round_seigniorage_rate = DEFAULT_ROUND_SEIGNIORAGE_RATE; let unbonding_delay = DEFAULT_UNBONDING_DELAY; let genesis_timestamp_millis = DEFAULT_GENESIS_TIMESTAMP_MILLIS; - let refund_handling = DEFAULT_REFUND_HANDLING; - let fee_handling = DEFAULT_FEE_HANDLING; GenesisConfigBuilder::default() .with_accounts(accounts) @@ -150,8 +144,6 @@ pub fn create_genesis_config(accounts: Vec) -> GenesisConfig { .with_round_seigniorage_rate(round_seigniorage_rate) .with_unbonding_delay(unbonding_delay) .with_genesis_timestamp_millis(genesis_timestamp_millis) - .with_refund_handling(refund_handling) - .with_fee_handling(fee_handling) .build() } @@ -159,58 +151,22 @@ pub fn create_genesis_config(accounts: Vec) -> GenesisConfig { pub fn create_run_genesis_request(accounts: Vec) -> GenesisRequest { let config = create_genesis_config(accounts); GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ) } -/// Returns a `Vec` representing gas consts for an [`ExecutionResult`]. -pub fn get_exec_costs, I: IntoIterator>( - exec_response: I, -) -> Vec { - exec_response - .into_iter() - .map(|res| res.as_ref().cost()) - .collect() -} - -/// Returns the success result of the `ExecutionResult`. -/// # Panics -/// Panics if `response` is `None`. -pub fn get_success_result(response: &[Rc]) -> &ExecutionResult { - response.get(0).expect("should have a result") -} - /// Returns an error if the `ExecutionResult` has an error. +/// /// # Panics -/// Panics if the result is `None`. -/// Panics if the result does not have a precondition failure. -/// Panics if result.as_error() is `None`. -pub fn get_precondition_failure(response: &[Rc]) -> &Error { - let result = response.get(0).expect("should have a result"); +/// * Panics if the result does not have a precondition failure. +/// * Panics if result.as_error() is `None`. +pub fn get_precondition_failure(exec_result: &WasmV1Result) -> &Error { assert!( - result.has_precondition_failure(), + exec_result.has_precondition_failure(), "should be a precondition failure" ); - result.as_error().expect("should have an error") -} - -/// Returns a `String` concatenated from all of the error messages from the `ExecutionResult`. -pub fn get_error_message, I: IntoIterator>( - execution_result: I, -) -> String { - let errors = execution_result - .into_iter() - .enumerate() - .filter_map(|(i, result)| { - if let ExecutionResult::Failure { error, .. } = result.as_ref() { - Some(format!("{}: {:?}", i, error)) - } else { - None - } - }) - .collect::>(); - errors.join("\n") + exec_result.error().expect("should have an error") } diff --git a/execution_engine_testing/test_support/src/wasm_test_builder.rs b/execution_engine_testing/test_support/src/wasm_test_builder.rs index 8eeb748f13..7400857f96 100644 --- a/execution_engine_testing/test_support/src/wasm_test_builder.rs +++ b/execution_engine_testing/test_support/src/wasm_test_builder.rs @@ -3,6 +3,7 @@ use std::{ convert::{TryFrom, TryInto}, ffi::OsStr, fs, + iter::{self, FromIterator}, ops::Deref, path::{Path, PathBuf}, rc::Rc, @@ -13,20 +14,22 @@ use filesize::PathExt; use lmdb::DatabaseFlags; use num_rational::Ratio; use num_traits::{CheckedMul, Zero}; +use tempfile::TempDir; use casper_execution_engine::engine_state::{ - execute_request::ExecuteRequest, execution_result::ExecutionResult, Error, ExecutionEngineV1, - DEFAULT_MAX_QUERY_DEPTH, + Error, ExecutionEngineV1, WasmV1Request, WasmV1Result, DEFAULT_MAX_QUERY_DEPTH, }; use casper_storage::{ data_access_layer::{ - BalanceRequest, BalanceResult, BidsRequest, BlockRewardsRequest, BlockRewardsResult, + balance::BalanceHandling, AuctionMethod, BalanceIdentifier, BalanceRequest, BalanceResult, + BiddingRequest, BiddingResult, BidsRequest, BlockRewardsRequest, BlockRewardsResult, BlockStore, DataAccessLayer, EraValidatorsRequest, EraValidatorsResult, FeeRequest, FeeResult, FlushRequest, FlushResult, GenesisRequest, GenesisResult, ProtocolUpgradeRequest, ProtocolUpgradeResult, PruneRequest, PruneResult, QueryRequest, - QueryResult, StepRequest, StepResult, SystemEntityRegistryPayload, - SystemEntityRegistryRequest, SystemEntityRegistryResult, SystemEntityRegistrySelector, - TrieRequest, + QueryResult, RoundSeigniorageRateRequest, RoundSeigniorageRateResult, StepRequest, + StepResult, SystemEntityRegistryPayload, SystemEntityRegistryRequest, + SystemEntityRegistryResult, SystemEntityRegistrySelector, TotalSupplyRequest, + TotalSupplyResult, TransferRequest, TrieRequest, }, global_state::{ state::{ @@ -50,25 +53,23 @@ use casper_types::{ runtime_args, system::{ auction::{ - BidKind, EraValidators, UnbondingPurse, UnbondingPurses, ValidatorWeights, - WithdrawPurses, ARG_ERA_END_TIMESTAMP_MILLIS, ARG_EVICTED_VALIDATORS, - AUCTION_DELAY_KEY, ERA_ID_KEY, METHOD_RUN_AUCTION, UNBONDING_DELAY_KEY, + BidKind, EraValidators, UnbondingPurses, ValidatorWeights, WithdrawPurses, + ARG_ERA_END_TIMESTAMP_MILLIS, ARG_EVICTED_VALIDATORS, AUCTION_DELAY_KEY, ERA_ID_KEY, + METHOD_RUN_AUCTION, UNBONDING_DELAY_KEY, }, - mint::{ROUND_SEIGNIORAGE_RATE_KEY, TOTAL_SUPPLY_KEY}, AUCTION, HANDLE_PAYMENT, MINT, STANDARD_PAYMENT, }, - AddressableEntity, AddressableEntityHash, AuctionCosts, ByteCode, ByteCodeAddr, ByteCodeHash, - CLTyped, CLValue, Contract, DeployHash, DeployInfo, Digest, EntityAddr, EraId, Gas, - HandlePaymentCosts, Key, KeyTag, MintCosts, Motes, Package, PackageHash, ProtocolUpgradeConfig, - ProtocolVersion, PublicKey, RefundHandling, StoredValue, SystemEntityRegistry, Transfer, - TransferAddr, URef, OS_PAGE_SIZE, U512, + AddressableEntity, AddressableEntityHash, AuctionCosts, BlockTime, ByteCode, ByteCodeAddr, + ByteCodeHash, CLTyped, CLValue, Contract, Digest, EntityAddr, EraId, Gas, HandlePaymentCosts, + HoldsEpoch, InitiatorAddr, Key, KeyTag, MintCosts, Motes, Package, PackageHash, + ProtocolUpgradeConfig, ProtocolVersion, PublicKey, RefundHandling, StoredValue, + SystemEntityRegistry, TransactionHash, TransactionV1Hash, URef, OS_PAGE_SIZE, U512, }; -use tempfile::TempDir; use crate::{ - chainspec_config::{ChainspecConfig, PRODUCTION_PATH}, - utils, ExecuteRequestBuilder, StepRequestBuilder, DEFAULT_GAS_PRICE, DEFAULT_PROPOSER_ADDR, - DEFAULT_PROTOCOL_VERSION, SYSTEM_ADDR, + chainspec_config::{ChainspecConfig, CHAINSPEC_SYMLINK}, + ExecuteRequest, ExecuteRequestBuilder, StepRequestBuilder, DEFAULT_GAS_PRICE, + DEFAULT_PROPOSER_ADDR, DEFAULT_PROTOCOL_VERSION, SYSTEM_ADDR, }; /// LMDB initial map size is calculated based on DEFAULT_LMDB_PAGES and systems page size. @@ -83,6 +84,7 @@ pub(crate) const DEFAULT_MAX_READERS: u32 = 512; const GLOBAL_STATE_DIR: &str = "global_state"; /// A wrapper structure that groups an entity alongside its namedkeys. +#[derive(Debug)] pub struct EntityWithNamedKeys { entity: AddressableEntity, named_keys: NamedKeys, @@ -122,8 +124,7 @@ pub struct WasmTestBuilder { execution_engine: Rc, /// The chainspec. chainspec: ChainspecConfig, - /// [`ExecutionResult`] is wrapped in [`Rc`] to work around a missing [`Clone`] implementation. - exec_results: Vec>>, + exec_results: Vec, upgrade_results: Vec, prune_results: Vec, genesis_hash: Option, @@ -167,7 +168,8 @@ impl WasmTestBuilder { /// Execute and commit transforms from an ExecuteRequest into a scratch global state. /// You MUST call write_scratch_to_lmdb to flush these changes to LmdbGlobalState. - pub fn scratch_exec_and_commit(&mut self, mut exec_request: ExecuteRequest) -> &mut Self { + #[allow(deprecated)] + pub fn scratch_exec_and_commit(&mut self, mut exec_request: WasmV1Request) -> &mut Self { if self.scratch_global_state.is_none() { self.scratch_global_state = Some(self.data_access_layer.get_scratch_global_state()); } @@ -177,35 +179,24 @@ impl WasmTestBuilder { .as_ref() .expect("scratch state should exist"); - // Scratch still requires that one deploy be executed and committed at a time. - let exec_request = { - let hash = self.post_state_hash.expect("expected post_state_hash"); - exec_request.parent_state_hash = hash; - exec_request - }; + exec_request.state_hash = self.post_state_hash.expect("expected post_state_hash"); - let mut exec_results = Vec::new(); // First execute the request against our scratch global state. - let maybe_exec_results = self.execution_engine.exec(cached_state, exec_request); - for execution_result in maybe_exec_results.unwrap() { - let _post_state_hash = cached_state - .commit( - self.post_state_hash.expect("requires a post_state_hash"), - execution_result.effects().clone(), - ) - .expect("should commit"); + let execution_result = self.execution_engine.execute(cached_state, exec_request); + let _post_state_hash = cached_state + .commit( + self.post_state_hash.expect("requires a post_state_hash"), + execution_result.effects().clone(), + ) + .expect("should commit"); - // Save transforms and execution results for WasmTestBuilder. - self.effects.push(execution_result.effects().clone()); - exec_results.push(Rc::new(execution_result)) - } - self.exec_results.push(exec_results); + // Save transforms and execution results for WasmTestBuilder. + self.effects.push(execution_result.effects().clone()); + self.exec_results.push(execution_result); self } } -// TODO: Deriving `Clone` for `WasmTestBuilder` doesn't work correctly (unsure why), so -// implemented by hand here. Try to derive in the future with a different compiler version. impl Clone for WasmTestBuilder { fn clone(&self) -> Self { WasmTestBuilder { @@ -249,7 +240,7 @@ pub type LmdbWasmTestBuilder = WasmTestBuilder> impl Default for LmdbWasmTestBuilder { fn default() -> Self { - Self::new_temporary_with_chainspec(&*PRODUCTION_PATH) + Self::new_temporary_with_chainspec(&*CHAINSPEC_SYMLINK) } } @@ -273,6 +264,9 @@ impl LmdbWasmTestBuilder { .write_scratch_to_db(pre_state_hash, scratch_state) .unwrap(); self.post_state_hash = Some(post_state_hash); + let mut engine_config = self.chainspec.engine_config(); + engine_config.set_protocol_version(upgrade_config.new_protocol_version()); + self.execution_engine = Rc::new(ExecutionEngineV1::new(engine_config)); ProtocolUpgradeResult::Success { post_state_hash, effects, @@ -342,6 +336,7 @@ impl LmdbWasmTestBuilder { fn create_or_open>( global_state_dir: T, chainspec: ChainspecConfig, + protocol_version: ProtocolVersion, mode: GlobalStateMode, ) -> Self { let _ = env_logger::try_init(); @@ -388,7 +383,8 @@ impl LmdbWasmTestBuilder { state: global_state, max_query_depth, }); - let engine_config = chainspec.engine_config(); + let mut engine_config = chainspec.engine_config(); + engine_config.set_protocol_version(protocol_version); let engine_state = ExecutionEngineV1::new(engine_config); let post_state_hash = mode.post_state_hash(); @@ -428,7 +424,7 @@ impl LmdbWasmTestBuilder { /// Returns an [`LmdbWasmTestBuilder`] with configuration and values from /// the production chainspec. pub fn new_with_production_chainspec + ?Sized>(data_dir: &T) -> Self { - Self::new_with_chainspec(data_dir, &*PRODUCTION_PATH) + Self::new_with_chainspec(data_dir, &*CHAINSPEC_SYMLINK) } /// Returns a new [`LmdbWasmTestBuilder`]. @@ -441,10 +437,16 @@ impl LmdbWasmTestBuilder { pub fn open + ?Sized>( data_dir: &T, chainspec: ChainspecConfig, + protocol_version: ProtocolVersion, post_state_hash: Digest, ) -> Self { let global_state_path = Self::global_state_dir(data_dir); - Self::open_raw(global_state_path, chainspec, post_state_hash) + Self::open_raw( + global_state_path, + chainspec, + protocol_version, + post_state_hash, + ) } /// Creates a new instance of builder using the supplied configurations, opening wrapped LMDBs @@ -453,11 +455,13 @@ impl LmdbWasmTestBuilder { pub fn open_raw>( global_state_dir: T, chainspec: ChainspecConfig, + protocol_version: ProtocolVersion, post_state_hash: Digest, ) -> Self { Self::create_or_open( global_state_dir, chainspec, + protocol_version, GlobalStateMode::Open(post_state_hash), ) } @@ -474,6 +478,7 @@ impl LmdbWasmTestBuilder { let mut builder = Self::create_or_open( temp_dir.path(), chainspec, + DEFAULT_PROTOCOL_VERSION, GlobalStateMode::Create(database_flags), ); @@ -540,6 +545,20 @@ impl LmdbWasmTestBuilder { } self } + + /// Runs a [`TransferRequest`] and commits the resulting effects. + pub fn transfer_and_commit(&mut self, mut transfer_request: TransferRequest) -> &mut Self { + let pre_state_hash = self.post_state_hash.expect("expected post_state_hash"); + transfer_request.set_state_hash_and_config(pre_state_hash, self.native_runtime_config()); + let transfer_result = self.data_access_layer.transfer(transfer_request); + let gas = Gas::new(self.chainspec.system_costs_config.mint_costs().transfer); + let execution_result = WasmV1Result::from_transfer_result(transfer_result, gas).unwrap(); + let effects = execution_result.effects().clone(); + self.effects.push(effects.clone()); + self.exec_results.push(execution_result); + self.commit_transforms(pre_state_hash, effects); + self + } } impl WasmTestBuilder @@ -568,15 +587,15 @@ where self } - fn query_system_contract_registry( + fn query_system_entity_registry( &self, post_state_hash: Option, ) -> Option { match self.query(post_state_hash, Key::SystemEntityRegistry, &[]) { Ok(StoredValue::CLValue(cl_registry)) => { - let system_contract_registry = + let system_entity_registry = CLValue::into_t::(cl_registry).unwrap(); - Some(system_contract_registry) + Some(system_entity_registry) } Ok(_) => None, Err(_) => None, @@ -613,7 +632,7 @@ where ) -> Result { let entity_addr = self .get_entity_hash_by_account_hash(account_hash) - .map(|entity_hash| EntityAddr::new_account_entity_addr(entity_hash.value())) + .map(|entity_hash| EntityAddr::new_account(entity_hash.value())) .expect("must get EntityAddr"); self.query_named_key(maybe_post_state, entity_addr, name) } @@ -679,86 +698,161 @@ where /// Queries for the total supply of token. /// # Panics /// Panics if the total supply can't be found. - pub fn total_supply(&self, maybe_post_state: Option) -> U512 { - let mint_entity_hash = self - .get_system_entity_hash(MINT) - .expect("should have mint_contract_hash"); - - let mint_key = Key::addressable_entity_key(EntityKindTag::System, mint_entity_hash); - - let result = self.query(maybe_post_state, mint_key, &[TOTAL_SUPPLY_KEY.to_string()]); - - let total_supply: U512 = if let Ok(StoredValue::CLValue(total_supply)) = result { - total_supply.into_t().expect("total supply should be U512") + pub fn total_supply( + &self, + maybe_post_state: Option, + protocol_version: ProtocolVersion, + ) -> U512 { + let post_state = maybe_post_state + .or(self.post_state_hash) + .expect("builder must have a post-state hash"); + let result = self + .data_access_layer + .total_supply(TotalSupplyRequest::new(post_state, protocol_version)); + if let TotalSupplyResult::Success { total_supply } = result { + total_supply } else { - panic!("mint should track total supply"); - }; + panic!("total supply should exist at every root hash {:?}", result); + } + } - total_supply + /// Queries for the round seigniorage rate. + /// # Panics + /// Panics if the total supply or seigniorage rate can't be found. + pub fn round_seigniorage_rate( + &mut self, + maybe_post_state: Option, + protocol_version: ProtocolVersion, + ) -> Ratio { + let post_state = maybe_post_state + .or(self.post_state_hash) + .expect("builder must have a post-state hash"); + let result = + self.data_access_layer + .round_seigniorage_rate(RoundSeigniorageRateRequest::new( + post_state, + protocol_version, + )); + if let RoundSeigniorageRateResult::Success { rate } = result { + rate + } else { + panic!( + "round seigniorage rate should exist at every root hash {:?}", + result + ); + } } /// Queries for the base round reward. /// # Panics /// Panics if the total supply or seigniorage rate can't be found. - pub fn base_round_reward(&mut self, maybe_post_state: Option) -> U512 { - let mint_named_keys = - self.get_named_keys(EntityAddr::System(self.get_mint_contract_hash().value())); - - let total_supply_uref = *mint_named_keys - .get(TOTAL_SUPPLY_KEY) - .expect("must track total supply") - .as_uref() - .expect("must get uref"); - - let round_seigniorage_rate_uref = *mint_named_keys - .get(ROUND_SEIGNIORAGE_RATE_KEY) - .expect("must track round seigniorage rate"); - - let total_supply = self - .query(maybe_post_state, Key::URef(total_supply_uref), &[]) - .expect("must read value under total supply URef") - .into_cl_value() - .expect("must convert into CL value") - .into_t::() - .expect("must convert into U512"); - - let rate = self - .query(maybe_post_state, round_seigniorage_rate_uref, &[]) - .expect("must read value") - .into_cl_value() - .expect("must conver to cl value") - .into_t::>() - .expect("must conver to ratio"); - + pub fn base_round_reward( + &mut self, + maybe_post_state: Option, + protocol_version: ProtocolVersion, + ) -> U512 { + let post_state = maybe_post_state + .or(self.post_state_hash) + .expect("builder must have a post-state hash"); + let total_supply = self.total_supply(Some(post_state), protocol_version); + let rate = self.round_seigniorage_rate(Some(post_state), protocol_version); rate.checked_mul(&Ratio::from(total_supply)) .map(|ratio| ratio.to_integer()) .expect("must get base round reward") } - /// Runs an [`ExecuteRequest`]. - pub fn exec(&mut self, mut exec_request: ExecuteRequest) -> &mut Self { - let exec_request = { - let hash = self.post_state_hash.expect("expected post_state_hash"); - exec_request.parent_state_hash = hash; - exec_request - }; + /// Direct auction interactions for stake management. + pub fn bidding( + &mut self, + maybe_post_state: Option, + protocol_version: ProtocolVersion, + initiator: InitiatorAddr, + auction_method: AuctionMethod, + ) -> BiddingResult { + let post_state = maybe_post_state + .or(self.post_state_hash) + .expect("builder must have a post-state hash"); + + let transaction_hash = TransactionHash::V1(TransactionV1Hash::default()); + let authorization_keys = BTreeSet::from_iter(iter::once(initiator.account_hash())); + + let config = &self.chainspec; + let fee_handling = config.core_config.fee_handling; + let refund_handling = config.core_config.refund_handling; + let vesting_schedule_period_millis = config.core_config.vesting_schedule_period.millis(); + let allow_auction_bids = config.core_config.allow_auction_bids; + let compute_rewards = config.core_config.compute_rewards; + let max_delegators_per_validator = config.core_config.max_delegators_per_validator; + let minimum_delegation_amount = config.core_config.minimum_delegation_amount; + let balance_hold_interval = config.core_config.balance_hold_interval.millis(); + + let native_runtime_config = casper_storage::system::runtime_native::Config::new( + TransferConfig::Unadministered, + fee_handling, + refund_handling, + vesting_schedule_period_millis, + allow_auction_bids, + compute_rewards, + max_delegators_per_validator, + minimum_delegation_amount, + balance_hold_interval, + ); + + let bidding_req = BiddingRequest::new( + native_runtime_config, + post_state, + protocol_version, + transaction_hash, + initiator, + authorization_keys, + auction_method, + ); + self.data_access_layer().bidding(bidding_req) + } + + /// Runs an optional custom payment [`WasmV1Request`] and a session `WasmV1Request`. + /// + /// If the custom payment is `Some` and its execution fails, the session request is not + /// attempted. + pub fn exec(&mut self, mut execute_request: ExecuteRequest) -> &mut Self { + let mut effects = Effects::new(); + if let Some(mut payment) = execute_request.custom_payment { + payment.state_hash = self.post_state_hash.expect("expected post_state_hash"); + let payment_result = self + .execution_engine + .execute(self.data_access_layer.as_ref(), payment); + // If executing payment code failed, record this and exit without attempting session + // execution. + effects = payment_result.effects().clone(); + let payment_failed = payment_result.error().is_some(); + self.exec_results.push(payment_result); + if payment_failed { + self.effects.push(effects); + return self; + } + } + execute_request.session.state_hash = + self.post_state_hash.expect("expected post_state_hash"); - let maybe_exec_results = self + let session_result = self .execution_engine - .exec(self.data_access_layer.as_ref(), exec_request); - assert!(maybe_exec_results.is_ok()); - // Parse deploy results - let execution_results = maybe_exec_results.as_ref().unwrap(); + .execute(self.data_access_layer.as_ref(), execute_request.session); // Cache transformations - self.effects - .extend(execution_results.iter().map(|res| res.effects().clone())); - self.exec_results.push( - maybe_exec_results - .unwrap() - .into_iter() - .map(Rc::new) - .collect(), - ); + effects.append(session_result.effects().clone()); + self.effects.push(effects); + self.exec_results.push(session_result); + self + } + + /// Execute a `WasmV1Request`. + pub fn exec_wasm_v1(&mut self, mut request: WasmV1Request) -> &mut Self { + request.state_hash = self.post_state_hash.expect("expected post_state_hash"); + let result = self + .execution_engine + .execute(self.data_access_layer.as_ref(), request); + let effects = result.effects().clone(); + self.exec_results.push(result); + self.effects.push(effects); self } @@ -783,8 +877,6 @@ where } /// Upgrades the execution engine. - /// - /// If `engine_config` is set to None, then it is defaulted to the current one. pub fn upgrade(&mut self, upgrade_config: &mut ProtocolUpgradeConfig) -> &mut Self { let pre_state_hash = self.post_state_hash.expect("should have state hash"); upgrade_config.with_pre_state_hash(pre_state_hash); @@ -796,6 +888,9 @@ where post_state_hash, .. } = result { + let mut engine_config = self.chainspec.engine_config(); + engine_config.set_protocol_version(upgrade_config.new_protocol_version()); + self.execution_engine = Rc::new(ExecutionEngineV1::new(engine_config)); self.post_state_hash = Some(post_state_hash); } @@ -810,7 +905,7 @@ where evicted_validators: Vec, ) -> &mut Self { let auction = self.get_auction_contract_hash(); - let run_request = ExecuteRequestBuilder::contract_call_by_hash( + let exec_request = ExecuteRequestBuilder::contract_call_by_hash( *SYSTEM_ADDR, auction, METHOD_RUN_AUCTION, @@ -820,7 +915,7 @@ where }, ) .build(); - self.exec(run_request).expect_success().commit() + self.exec(exec_request).expect_success().commit() } /// Increments engine state. @@ -847,24 +942,16 @@ where .collect(); let allow_unrestricted = self.chainspec.core_config.allow_unrestricted_transfers; let transfer_config = TransferConfig::new(administrators, allow_unrestricted); - - let fee_handling = self.chainspec.core_config.fee_handling; - let refund_handling = self.chainspec.core_config.refund_handling; - let vesting_schedule_period_millis = - self.chainspec.core_config.vesting_schedule_period.millis(); - let allow_auction_bids = self.chainspec.core_config.allow_auction_bids; - let compute_rewards = self.chainspec.core_config.compute_rewards; - let max_delegators_per_validator = self.chainspec.core_config.max_delegators_per_validator; - let minimum_delegation_amount = self.chainspec.core_config.minimum_delegation_amount; NativeRuntimeConfig::new( transfer_config, - fee_handling, - refund_handling, - vesting_schedule_period_millis, - allow_auction_bids, - compute_rewards, - max_delegators_per_validator, - minimum_delegation_amount, + self.chainspec.core_config.fee_handling, + self.chainspec.core_config.refund_handling, + self.chainspec.core_config.vesting_schedule_period.millis(), + self.chainspec.core_config.allow_auction_bids, + self.chainspec.core_config.compute_rewards, + self.chainspec.core_config.max_delegators_per_validator, + self.chainspec.core_config.minimum_delegation_amount, + self.chainspec.core_config.balance_hold_interval.millis(), ) } @@ -876,13 +963,18 @@ where block_time: u64, ) -> FeeResult { let native_runtime_config = self.native_runtime_config(); + let holds_epoch = HoldsEpoch::from_millis( + block_time, + self.chainspec.core_config.balance_hold_interval.millis(), + ); let pre_state_hash = pre_state_hash.or(self.post_state_hash).unwrap(); let fee_req = FeeRequest::new( native_runtime_config, pre_state_hash, protocol_version, - block_time, + block_time.into(), + holds_epoch, ); let fee_result = self.data_access_layer.distribute_fees(fee_req); @@ -902,7 +994,7 @@ where pre_state_hash: Option, protocol_version: ProtocolVersion, rewards: BTreeMap, - time: u64, + block_time: u64, ) -> BlockRewardsResult { let pre_state_hash = pre_state_hash.or(self.post_state_hash).unwrap(); let native_runtime_config = self.native_runtime_config(); @@ -910,7 +1002,7 @@ where native_runtime_config, pre_state_hash, protocol_version, - time, + BlockTime::new(block_time), rewards, ); let distribute_block_rewards_result = self @@ -930,15 +1022,10 @@ where /// Expects a successful run #[track_caller] pub fn expect_success(&mut self) -> &mut Self { - // Check first result, as only first result is interesting for a simple test - let exec_results = self + let exec_result = self .get_last_exec_result() - .expect("Expected to be called after run()"); - let exec_result = exec_results - .get(0) - .expect("Unable to get first deploy result"); - - if exec_result.is_failure() { + .expect("Expected to be called after exec()"); + if exec_result.error().is_some() { panic!( "Expected successful execution result, but instead got: {:#?}", exec_result, @@ -949,44 +1036,47 @@ where /// Expects a failed run pub fn expect_failure(&mut self) -> &mut Self { - // Check first result, as only first result is interesting for a simple test - let exec_results = self + let exec_result = self .get_last_exec_result() - .expect("Expected to be called after run()"); - let exec_result = exec_results - .get(0) - .expect("Unable to get first deploy result"); - - if exec_result.is_success() { + .expect("Expected to be called after exec()"); + if exec_result.error().is_none() { panic!( "Expected failed execution result, but instead got: {:?}", exec_result, ); } - self } - /// Returns `true` if the las exec had an error, otherwise returns false. + /// Returns `true` if the last exec had an error, otherwise returns false. + #[track_caller] pub fn is_error(&self) -> bool { self.get_last_exec_result() - .expect("Expected to be called after run()") - .get(0) - .expect("Unable to get first execution result") - .is_failure() + .expect("Expected to be called after exec()") + .error() + .is_some() } - /// Returns an `Option` if the last exec had an error. + /// Returns an `engine_state::Error` if the last exec had an error, otherwise `None`. + #[track_caller] pub fn get_error(&self) -> Option { self.get_last_exec_result() - .expect("Expected to be called after run()") - .get(0) - .expect("Unable to get first deploy result") - .as_error() + .expect("Expected to be called after exec()") + .error() .cloned() } + /// Returns the error message of the last exec. + #[track_caller] + pub fn get_error_message(&self) -> Option { + self.get_last_exec_result() + .expect("Expected to be called after exec()") + .error() + .map(|error| error.to_string()) + } + /// Gets `Effects` of all previous runs. + #[track_caller] pub fn get_effects(&self) -> Vec { self.effects.clone() } @@ -1019,7 +1109,7 @@ where } fn get_system_entity_hash(&self, contract_name: &str) -> Option { - self.query_system_contract_registry(self.post_state_hash)? + self.query_system_entity_registry(self.post_state_hash)? .get(contract_name) .copied() } @@ -1072,17 +1162,13 @@ where } /// Returns the last results execs. - pub fn get_last_exec_result(&self) -> Option>> { - let exec_results = self.exec_results.last()?; - - Some(exec_results.iter().map(Rc::clone).collect()) + pub fn get_last_exec_result(&self) -> Option { + self.exec_results.last().cloned() } /// Returns the owned results of a specific exec. - pub fn get_exec_result_owned(&self, index: usize) -> Option>> { - let exec_results = self.exec_results.get(index)?; - - Some(exec_results.iter().map(Rc::clone).collect()) + pub fn get_exec_result_owned(&self, index: usize) -> Option { + self.exec_results.get(index).cloned() } /// Returns a count of exec results. @@ -1137,10 +1223,20 @@ where pub fn get_purse_balance_result( &self, protocol_version: ProtocolVersion, - purse: URef, + balance_identifier: BalanceIdentifier, + block_time: u64, ) -> BalanceResult { + let hold_interval = self.chainspec.core_config.balance_hold_interval.millis(); + let holds_epoch = HoldsEpoch::from_millis(block_time, hold_interval); + let balance_handling = BalanceHandling::Available { holds_epoch }; + let state_root_hash: Digest = self.post_state_hash.expect("should have post_state_hash"); - let request = BalanceRequest::from_purse(state_root_hash, protocol_version, purse); + let request = BalanceRequest::new( + state_root_hash, + protocol_version, + balance_identifier, + balance_handling, + ); self.data_access_layer.balance(request) } @@ -1149,10 +1245,18 @@ where &self, protocol_version: ProtocolVersion, public_key: PublicKey, + block_time: u64, ) -> BalanceResult { let state_root_hash: Digest = self.post_state_hash.expect("should have post_state_hash"); - let request = - BalanceRequest::from_public_key(state_root_hash, protocol_version, public_key); + let hold_interval = self.chainspec.core_config.balance_hold_interval.millis(); + let holds_epoch = HoldsEpoch::from_millis(block_time, hold_interval); + let balance_handling = BalanceHandling::Available { holds_epoch }; + let request = BalanceRequest::from_public_key( + state_root_hash, + protocol_version, + public_key, + balance_handling, + ); self.data_access_layer.balance(request) } @@ -1299,56 +1403,20 @@ where } } - /// Queries for a transfer by `TransferAddr`. - pub fn get_transfer(&self, transfer: TransferAddr) -> Option { - let transfer_value: StoredValue = self - .query(None, Key::Transfer(transfer), &[]) - .expect("should have transfer value"); - - if let StoredValue::Transfer(transfer) = transfer_value { - Some(transfer) - } else { - None - } - } - - /// Queries for deploy info by `DeployHash`. - pub fn get_deploy_info(&self, deploy_hash: DeployHash) -> Option { - let deploy_info_value: StoredValue = self - .query(None, Key::DeployInfo(deploy_hash), &[]) - .expect("should have deploy info value"); - - if let StoredValue::DeployInfo(deploy_info) = deploy_info_value { - Some(deploy_info) - } else { - None - } - } - - /// Returns a `Vec` representing execution consts. - pub fn exec_costs(&self, index: usize) -> Vec { - let exec_results = self - .get_exec_result_owned(index) - .expect("should have exec response"); - utils::get_exec_costs(exec_results) + /// Returns execution cost. + pub fn exec_cost(&self, index: usize) -> Gas { + self.exec_results + .get(index) + .map(WasmV1Result::consumed) + .unwrap() } /// Returns the `Gas` cost of the last exec. pub fn last_exec_gas_cost(&self) -> Gas { - let exec_results = self - .get_last_exec_result() - .expect("Expected to be called after run()"); - let exec_result = exec_results.get(0).expect("should have result"); - exec_result.cost() - } - - /// Returns the result of the last exec. - pub fn last_exec_result(&self) -> &ExecutionResult { - let exec_results = self - .exec_results + self.exec_results .last() - .expect("Expected to be called after run()"); - exec_results.get(0).expect("should have result").as_ref() + .map(WasmV1Result::consumed) + .unwrap() } /// Assert that last error is the expected one. @@ -1362,16 +1430,10 @@ where } } - /// Returns the error message of the last exec. - pub fn exec_error_message(&self, index: usize) -> Option { - let response = self.get_exec_result_owned(index)?; - Some(utils::get_error_message(response)) - } - /// Gets [`EraValidators`]. pub fn get_era_validators(&mut self) -> EraValidators { let state_hash = self.get_post_state_hash(); - let request = EraValidatorsRequest::new(state_hash, *DEFAULT_PROTOCOL_VERSION); + let request = EraValidatorsRequest::new(state_hash, DEFAULT_PROTOCOL_VERSION); let result = self.data_access_layer.era_validators(request); if let EraValidatorsResult::Success { era_validators } = result { @@ -1401,7 +1463,7 @@ where let entity_hash = self .get_entity_hash_by_account_hash(account_hash) .expect("must have entity hash"); - let entity_addr = EntityAddr::new_account_entity_addr(entity_hash.value()); + let entity_addr = EntityAddr::new_account(entity_hash.value()); self.get_named_keys(entity_addr) } @@ -1410,7 +1472,7 @@ where &self, contract_hash: AddressableEntityHash, ) -> NamedKeys { - let entity_addr = EntityAddr::new_contract_entity_addr(contract_hash.value()); + let entity_addr = EntityAddr::new_smart_contract(contract_hash.value()); self.get_named_keys(entity_addr) } @@ -1735,40 +1797,6 @@ where self } - /// Returns the results of all execs. - #[deprecated( - since = "2.3.0", - note = "use `get_last_exec_results` or `get_exec_result_owned` instead" - )] - pub fn get_exec_results(&self) -> &Vec>> { - &self.exec_results - } - - /// Returns the results of a specific exec. - #[deprecated(since = "2.3.0", note = "use `get_exec_result_owned` instead")] - pub fn get_exec_result(&self, index: usize) -> Option<&Vec>> { - self.exec_results.get(index) - } - - /// Gets [`UnbondingPurses`]. - #[deprecated(since = "2.3.0", note = "use `get_withdraw_purses` instead")] - pub fn get_withdraws(&mut self) -> UnbondingPurses { - let withdraw_purses = self.get_withdraw_purses(); - let unbonding_purses: UnbondingPurses = withdraw_purses - .iter() - .map(|(key, withdraw_purse)| { - ( - key.to_owned(), - withdraw_purse - .iter() - .map(|withdraw_purse| withdraw_purse.to_owned().into()) - .collect::>(), - ) - }) - .collect::>>(); - unbonding_purses - } - /// Calculates refunded amount from a last execution request. pub fn calculate_refund_amount(&self, payment_amount: U512) -> U512 { let gas_amount = Motes::from_gas(self.last_exec_gas_cost(), DEFAULT_GAS_PRICE) @@ -1778,7 +1806,7 @@ where RefundHandling::Refund { refund_ratio } | RefundHandling::Burn { refund_ratio } => { refund_ratio } - RefundHandling::None => Ratio::zero(), + RefundHandling::NoRefund => Ratio::zero(), }; let (numer, denom) = refund_ratio.into(); diff --git a/execution_engine_testing/tests/Cargo.toml b/execution_engine_testing/tests/Cargo.toml index 571f288262..6ad9f66d14 100644 --- a/execution_engine_testing/tests/Cargo.toml +++ b/execution_engine_testing/tests/Cargo.toml @@ -39,18 +39,3 @@ wat = "1.0.47" [features] use-as-wasm = ["casper-engine-test-support/use-as-wasm"] fixture-generators = [] - -[lib] -bench = false - -[[bench]] -name = "transfer_bench" -harness = false - -[[bench]] -name = "auction_bench" -harness = false - -[[bin]] -name = "disk_use" -path = "bin/disk_use.rs" diff --git a/execution_engine_testing/tests/benches/auction_bench.rs b/execution_engine_testing/tests/benches/auction_bench.rs deleted file mode 100644 index 693d1a0ab0..0000000000 --- a/execution_engine_testing/tests/benches/auction_bench.rs +++ /dev/null @@ -1,270 +0,0 @@ -use std::{path::Path, time::Duration}; - -use casper_execution_engine::engine_state::ExecuteRequest; -use criterion::{ - criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, Throughput, -}; -use rand::Rng; -use tempfile::TempDir; - -use casper_engine_test_support::{ - ChainspecConfig, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, - StepRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, - DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_AUCTION_DELAY, DEFAULT_CHAINSPEC_REGISTRY, - DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_GENESIS_TIMESTAMP_MILLIS, - DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_MINIMUM_DELEGATION_AMOUNT, - DEFAULT_PROPOSER_PUBLIC_KEY, DEFAULT_PROTOCOL_VERSION, DEFAULT_ROUND_SEIGNIORAGE_RATE, - DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY, DEFAULT_WASM_CONFIG, - MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, -}; -use casper_storage::data_access_layer::GenesisRequest; -use casper_types::{ - account::AccountHash, - runtime_args, - system::auction::{self}, - GenesisAccount, GenesisConfigBuilder, GenesisValidator, Motes, ProtocolVersion, PublicKey, - SecretKey, DEFAULT_DELEGATE_COST, U512, -}; - -const ARG_AMOUNT: &str = "amount"; -const ARG_TARGET: &str = "target"; -const ARG_ID: &str = "id"; - -const DELEGATION_AMOUNT: u64 = DEFAULT_MINIMUM_DELEGATION_AMOUNT; -const DELEGATION_RATE: u8 = 1; -const DELEGATOR_INITIAL_BALANCE: u64 = MINIMUM_ACCOUNT_CREATION_BALANCE; - -const VALIDATOR_BID_AMOUNT: u64 = 100; -const TIMESTAMP_INCREMENT_MILLIS: u64 = 30_000; - -/// Runs genesis, creates system, validator and delegator accounts, and funds the system account and -/// delegator accounts. -fn run_genesis_and_create_initial_accounts( - data_dir: &Path, - validator_keys: &[PublicKey], - delegator_accounts: Vec, -) -> LmdbWasmTestBuilder { - let mut builder = LmdbWasmTestBuilder::new_with_config(data_dir, ChainspecConfig::default()); - - let mut genesis_accounts = vec![ - GenesisAccount::account( - DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::MAX / u64::MAX), // enough motes - None, - ), - GenesisAccount::account( - DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - None, - ), - ]; - for validator in validator_keys { - genesis_accounts.push(GenesisAccount::account( - validator.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), - Some(GenesisValidator::new( - Motes::new(U512::from(VALIDATOR_BID_AMOUNT)), - DELEGATION_RATE, - )), - )) - } - let run_genesis_request = - create_run_genesis_request(validator_keys.len() as u32 + 2, genesis_accounts); - builder.run_genesis(run_genesis_request); - - // Setup the system account with enough cspr - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => *SYSTEM_ADDR, - ARG_AMOUNT => MINIMUM_ACCOUNT_CREATION_BALANCE, - ARG_ID => >::None, - }, - ) - .build(); - builder.exec(transfer); - builder.expect_success().commit(); - - for delegator_account in delegator_accounts { - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => delegator_account, - ARG_AMOUNT => DELEGATOR_INITIAL_BALANCE, - ARG_ID => >::None, - }, - ) - .build(); - builder.exec(transfer); - builder.expect_success().commit(); - } - builder -} - -fn create_run_genesis_request( - validator_slots: u32, - genesis_accounts: Vec, -) -> GenesisRequest { - let exec_config = { - GenesisConfigBuilder::new() - .with_accounts(genesis_accounts) - .with_wasm_config(*DEFAULT_WASM_CONFIG) - .with_system_config(*DEFAULT_SYSTEM_CONFIG) - .with_validator_slots(validator_slots) - .with_auction_delay(DEFAULT_AUCTION_DELAY) - .with_locked_funds_period_millis(DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS) - .with_round_seigniorage_rate(DEFAULT_ROUND_SEIGNIORAGE_RATE) - .with_unbonding_delay(DEFAULT_UNBONDING_DELAY) - .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) - .build() - }; - GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, - exec_config, - DEFAULT_CHAINSPEC_REGISTRY.clone(), - ) -} - -fn setup_bench_run_auction( - group: &mut BenchmarkGroup, - validator_count: usize, - delegator_count: usize, - protocol_version: ProtocolVersion, -) { - // Setup delegator public keys - let delegator_keys = generate_public_keys(delegator_count); - let validator_keys = generate_public_keys(validator_count); - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = run_genesis_and_create_initial_accounts( - data_dir.path(), - &validator_keys, - delegator_keys - .iter() - .map(|pk| pk.to_account_hash()) - .collect::>(), - ); - - let contract_hash = builder.get_auction_contract_hash(); - let mut next_validator_iter = validator_keys.iter().cycle(); - for delegator_public_key in delegator_keys { - let balance = builder - .get_public_key_balance_result(protocol_version, delegator_public_key.clone()) - .motes() - .cloned() - .unwrap(); - - assert_eq!(U512::from(DELEGATOR_INITIAL_BALANCE), balance); - - let delegation_amount = U512::from(DELEGATION_AMOUNT); - let delegator_account_hash = delegator_public_key.to_account_hash(); - let next_validator_key = next_validator_iter - .next() - .expect("should produce values forever"); - let delegate = create_delegate_request( - delegator_public_key, - next_validator_key.clone(), - delegation_amount, - delegator_account_hash, - contract_hash, - ); - builder.exec(delegate); - builder.expect_success(); - builder.commit(); - builder.clear_results(); - } - - let mut era_end_timestamp = TIMESTAMP_INCREMENT_MILLIS; - - group.bench_function( - format!( - "run_auction/validators/{}/delegators/{}", - validator_count, delegator_count - ), - |b| { - b.iter(|| { - era_end_timestamp += TIMESTAMP_INCREMENT_MILLIS; - step_and_run_auction(&mut builder) - }) - }, - ); -} - -fn create_delegate_request( - delegator_public_key: PublicKey, - next_validator_key: PublicKey, - delegation_amount: U512, - delegator_account_hash: AccountHash, - contract_hash: casper_types::AddressableEntityHash, -) -> ExecuteRequest { - let entry_point = auction::METHOD_DELEGATE; - let args = runtime_args! { - auction::ARG_DELEGATOR => delegator_public_key, - auction::ARG_VALIDATOR => next_validator_key, - auction::ARG_AMOUNT => delegation_amount, - }; - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let deploy = DeployItemBuilder::new() - .with_address(delegator_account_hash) - .with_stored_session_hash(contract_hash, entry_point, args) - .with_empty_payment_bytes( - runtime_args! { ARG_AMOUNT => U512::from(DEFAULT_DELEGATE_COST), }, - ) - .with_authorization_keys(&[delegator_account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() -} - -fn generate_public_keys(key_count: usize) -> Vec { - let mut ret = Vec::with_capacity(key_count); - for _ in 0..key_count { - let bytes: [u8; SecretKey::ED25519_LENGTH] = rand::random(); - let secret_key = SecretKey::ed25519_from_bytes(bytes).unwrap(); - let public_key = PublicKey::from(&secret_key); - ret.push(public_key); - } - ret -} - -fn step_and_run_auction(builder: &mut LmdbWasmTestBuilder) { - let step_request_builder = StepRequestBuilder::new() - .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(ProtocolVersion::V1_0_0); - - let step_request = step_request_builder - .with_next_era_id(builder.get_era() + 1) - .build(); - assert!(builder.step(step_request).is_success(), "should step"); -} - -pub fn auction_bench(c: &mut Criterion) { - let mut group = c.benchmark_group("auction_bench_group"); - let protocol_version = ProtocolVersion::V2_0_0; - /// Total number of validators, total number of delegators. Delegators will be spread - /// round-robin over the validators. - const VALIDATOR_DELEGATOR_COUNTS: [(usize, usize); 4] = - [(100, 8000), (150, 8000), (100, 10000), (150, 10000)]; - for (validator_count, delegator_count) in VALIDATOR_DELEGATOR_COUNTS { - group.sample_size(10); - group.measurement_time(Duration::from_secs(30)); - group.throughput(Throughput::Elements(1)); - println!( - "Starting bench of {} validators and {} delegators", - validator_count, delegator_count - ); - setup_bench_run_auction( - &mut group, - validator_count, - delegator_count, - protocol_version, - ); - println!("Ended bench"); - } - group.finish(); -} - -criterion_group!(benches, auction_bench); -criterion_main!(benches); diff --git a/execution_engine_testing/tests/benches/transfer_bench.rs b/execution_engine_testing/tests/benches/transfer_bench.rs deleted file mode 100644 index 389919d21b..0000000000 --- a/execution_engine_testing/tests/benches/transfer_bench.rs +++ /dev/null @@ -1,468 +0,0 @@ -use std::{path::Path, time::Duration}; - -use criterion::{ - criterion_group, criterion_main, - measurement::{Measurement, WallTime}, - BenchmarkGroup, Criterion, Throughput, -}; -use tempfile::TempDir; - -use casper_engine_test_support::{ - ChainspecConfig, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_execution_engine::engine_state::ExecuteRequest; -use casper_types::{account::AccountHash, runtime_args, Key, URef, U512}; - -const CONTRACT_CREATE_ACCOUNTS: &str = "create_accounts.wasm"; -const CONTRACT_CREATE_PURSES: &str = "create_purses.wasm"; -const CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT: &str = "transfer_to_existing_account.wasm"; -const CONTRACT_TRANSFER_TO_PURSE: &str = "transfer_to_purse.wasm"; - -/// Size of batch used in multiple execs benchmark, and multiple deploys per exec cases. -const TRANSFER_BATCH_SIZE: u64 = 3; -const TARGET_ADDR: AccountHash = AccountHash::new([127; 32]); -const ARG_AMOUNT: &str = "amount"; -const ARG_ID: &str = "id"; -const ARG_ACCOUNTS: &str = "accounts"; -const ARG_TOTAL_PURSES: &str = "total_purses"; -const ARG_TARGET: &str = "target"; -const ARG_TARGET_PURSE: &str = "target_purse"; - -const BLOCK_TRANSFER_COUNT: usize = 2500; - -/// Converts an integer into an array of type [u8; 32] by converting integer -/// into its big endian representation and embedding it at the end of the -/// range. -fn make_deploy_hash(i: u64) -> [u8; 32] { - let mut result = [128; 32]; - result[32 - 8..].copy_from_slice(&i.to_be_bytes()); - result -} - -fn bootstrap(data_dir: &Path, accounts: Vec, amount: U512) -> LmdbWasmTestBuilder { - let seed_amount = amount * accounts.len(); - let exec_request = ExecuteRequestBuilder::standard( - *DEFAULT_ACCOUNT_ADDR, - CONTRACT_CREATE_ACCOUNTS, - runtime_args! { ARG_ACCOUNTS => accounts, ARG_AMOUNT => seed_amount }, - ) - .build(); - - let mut builder = LmdbWasmTestBuilder::new_with_config(data_dir, ChainspecConfig::default()); - - builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) - .exec(exec_request) - .expect_success() - .commit(); - - builder -} - -fn create_purses( - builder: &mut LmdbWasmTestBuilder, - source: AccountHash, - total_purses: u64, - purse_amount: U512, -) -> Vec { - let seed_amount = purse_amount * total_purses; - let exec_request = ExecuteRequestBuilder::standard( - source, - CONTRACT_CREATE_PURSES, - runtime_args! { ARG_TOTAL_PURSES => total_purses, ARG_AMOUNT => seed_amount }, - ) - .build(); - - builder.exec(exec_request).expect_success().commit(); - - // Return creates purses for given account by filtering named key. - let named_keys = builder.get_named_keys_by_account_hash(source); - - (0..total_purses) - .map(|index| { - let purse_lookup_key = format!("purse:{}", index); - let purse_uref = named_keys - .get(&purse_lookup_key) - .and_then(Key::as_uref) - .unwrap_or_else(|| panic!("should get named key {} as uref", purse_lookup_key)); - *purse_uref - }) - .collect() -} - -/// Uses multiple exec requests with a single deploy to transfer tokens. Executes all transfers in -/// batch determined by value of TRANSFER_BATCH_SIZE. -fn transfer_to_account_multiple_execs( - builder: &mut LmdbWasmTestBuilder, - account: AccountHash, - should_commit: bool, -) { - let amount = U512::one(); - - for _ in 0..TRANSFER_BATCH_SIZE { - let exec_request = ExecuteRequestBuilder::standard( - *DEFAULT_ACCOUNT_ADDR, - CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT, - runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => amount, - }, - ) - .build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } - } -} - -/// Executes multiple deploys per single exec with based on TRANSFER_BATCH_SIZE. -fn transfer_to_account_multiple_deploys( - builder: &mut LmdbWasmTestBuilder, - account: AccountHash, - should_commit: bool, -) { - let mut exec_builder = ExecuteRequestBuilder::new(); - - for i in 0..TRANSFER_BATCH_SIZE { - let deploy = DeployItemBuilder::default() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) - .with_session_code( - CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT, - runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => U512::one(), - }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash(make_deploy_hash(i)) // deploy_hash - .build(); - exec_builder = exec_builder.push_deploy(deploy); - } - - let exec_request = exec_builder.build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } -} - -/// Uses multiple exec requests with a single deploy to transfer tokens from purse to purse. -/// Executes all transfers in batch determined by value of TRANSFER_BATCH_SIZE. -fn transfer_to_purse_multiple_execs( - builder: &mut LmdbWasmTestBuilder, - purse: URef, - should_commit: bool, -) { - let amount = U512::one(); - - for _ in 0..TRANSFER_BATCH_SIZE { - let exec_request = ExecuteRequestBuilder::standard( - TARGET_ADDR, - CONTRACT_TRANSFER_TO_PURSE, - runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => amount }, - ) - .build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } - } -} - -/// Executes multiple deploys per single exec with based on TRANSFER_BATCH_SIZE. -fn transfer_to_purse_multiple_deploys( - builder: &mut LmdbWasmTestBuilder, - purse: URef, - should_commit: bool, -) { - let mut exec_builder = ExecuteRequestBuilder::new(); - - for i in 0..TRANSFER_BATCH_SIZE { - let deploy = DeployItemBuilder::default() - .with_address(TARGET_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - CONTRACT_TRANSFER_TO_PURSE, - runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => U512::one() }, - ) - .with_authorization_keys(&[TARGET_ADDR]) - .with_deploy_hash(make_deploy_hash(i)) // deploy_hash - .build(); - exec_builder = exec_builder.push_deploy(deploy); - } - - let exec_request = exec_builder.build(); - - let builder = builder.exec(exec_request).expect_success(); - if should_commit { - builder.commit(); - } -} - -pub fn transfer_to_existing_accounts(group: &mut BenchmarkGroup, should_commit: bool) { - let target_account = TARGET_ADDR; - let bootstrap_accounts = vec![target_account]; - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = bootstrap(data_dir.path(), bootstrap_accounts.clone(), U512::one()); - - group.bench_function( - format!( - "transfer_to_existing_account_multiple_execs/{}/{}", - TRANSFER_BATCH_SIZE, should_commit - ), - |b| { - b.iter(|| { - // Execute multiple deploys with multiple exec requests - transfer_to_account_multiple_execs(&mut builder, target_account, should_commit) - }) - }, - ); - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = bootstrap(data_dir.path(), bootstrap_accounts, U512::one()); - - group.bench_function( - format!( - "transfer_to_existing_account_multiple_deploys_per_exec/{}/{}", - TRANSFER_BATCH_SIZE, should_commit - ), - |b| { - b.iter(|| { - // Execute multiple deploys with a single exec request - transfer_to_account_multiple_deploys(&mut builder, target_account, should_commit) - }) - }, - ); -} - -// Generate multiple purses as well as transfer requests between them with the specified count. -pub fn multiple_native_transfers( - group: &mut BenchmarkGroup, - transfer_count: usize, - purse_count: usize, - use_scratch: bool, -) where - M: Measurement, -{ - let target_account = TARGET_ADDR; - let bootstrap_accounts = vec![target_account]; - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = bootstrap( - data_dir.path(), - bootstrap_accounts, - U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - ); - - let purse_amount = U512::one(); - let purses = create_purses( - &mut builder, - target_account, - purse_count as u64, - purse_amount, - ); - - let mut purse_index = 0usize; - let mut exec_requests = Vec::with_capacity(transfer_count); - for _ in 0..transfer_count { - let account = { - let account = purses[purse_index]; - if purse_index == purses.len() - 1 { - purse_index = 0; - } else { - purse_index += 1; - } - account - }; - let mut exec_builder = ExecuteRequestBuilder::new(); - let runtime_args = runtime_args! { - ARG_TARGET => account, - ARG_AMOUNT => U512::one(), - ARG_ID => >::None - }; - let native_transfer = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .build(); - exec_builder = exec_builder.push_deploy(native_transfer); - let exec_request = exec_builder.build(); - exec_requests.push(exec_request); - } - - let criterion_metric_name = std::any::type_name::(); - - group.bench_function( - format!( - "type:{}/transfers:{}/purses:{}/metric:{}", - if use_scratch { "scratch" } else { "lmdb" }, - transfer_count, - purse_count, - criterion_metric_name, - ), - |b| { - b.iter(|| { - transfer_to_account_multiple_native_transfers( - &mut builder, - &exec_requests, - use_scratch, - ) - }) - }, - ); -} - -/// This test simulates flushing at the end of a block. -fn transfer_to_account_multiple_native_transfers( - builder: &mut LmdbWasmTestBuilder, - execute_requests: &[ExecuteRequest], - use_scratch: bool, -) { - for exec_request in execute_requests { - let request = ExecuteRequest::new( - exec_request.parent_state_hash, - exec_request.block_time, - exec_request.deploys.clone(), - exec_request.protocol_version, - exec_request.proposer.clone(), - ); - if use_scratch { - builder.scratch_exec_and_commit(request).expect_success(); - } else { - builder.exec(request).expect_success(); - builder.commit(); - } - } - if use_scratch { - builder.write_scratch_to_db(); - } - // flush to disk only after entire block (simulates manual_sync_enabled=true config entry) - builder.flush_environment(); - - // WasmTestBuilder holds on to all execution results. This needs to be cleared to reduce - // overhead in this test - it will likely OOM without. - builder.clear_results(); -} - -pub fn transfer_to_existing_purses(group: &mut BenchmarkGroup, should_commit: bool) { - let target_account = TARGET_ADDR; - let bootstrap_accounts = vec![target_account]; - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = bootstrap( - data_dir.path(), - bootstrap_accounts.clone(), - U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE) * 10, - ); - - let purse_amount = U512::one(); - let purses = create_purses(&mut builder, target_account, 1, purse_amount); - - group.bench_function( - format!( - "transfer_to_purse_multiple_execs/{}/{}", - TRANSFER_BATCH_SIZE, should_commit - ), - |b| { - let target_purse = purses[0]; - b.iter(|| { - // Execute multiple deploys with multiple exec request - transfer_to_purse_multiple_execs(&mut builder, target_purse, should_commit) - }) - }, - ); - - let data_dir = TempDir::new().expect("should create temp dir"); - let mut builder = bootstrap( - data_dir.path(), - bootstrap_accounts, - U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE) * 10, - ); - let purses = create_purses(&mut builder, TARGET_ADDR, 1, U512::one()); - - group.bench_function( - format!( - "transfer_to_purse_multiple_deploys_per_exec/{}/{}", - TRANSFER_BATCH_SIZE, should_commit - ), - |b| { - let target_purse = purses[0]; - b.iter(|| { - // Execute multiple deploys with a single exec request - transfer_to_purse_multiple_deploys(&mut builder, target_purse, should_commit) - }) - }, - ); -} - -pub fn native_transfer_bench(c: &mut Criterion) -where - M: Measurement, -{ - let mut group: BenchmarkGroup<'_, M> = c.benchmark_group("tps_native"); - - // Minimum number of samples and measurement times to decrease the total time of this benchmark. - // This may or may not decrease the quality of the numbers. - group.sample_size(10); - group.measurement_time(Duration::from_secs(60)); - - // Measure by elements where one element per second is one transaction per second - group.throughput(Throughput::Elements(BLOCK_TRANSFER_COUNT as u64)); - - for purse_count in [50, 100] { - for transfer_count in [500, 1500, 2500usize] { - // baseline, one deploy per exec request - multiple_native_transfers(&mut group, transfer_count, purse_count, true); - multiple_native_transfers(&mut group, transfer_count, purse_count, false); - } - } - - group.finish(); -} - -pub fn transfer_bench(c: &mut Criterion) { - let mut group = c.benchmark_group("tps"); - - // Minimum number of samples and measurement times to decrease the total time of this benchmark. - // This may or may not decrease the quality of the numbers. - group.sample_size(10); - group.measurement_time(Duration::from_secs(10)); - - // Measure by elements where one element per second is one transaction per second - group.throughput(Throughput::Elements(TRANSFER_BATCH_SIZE)); - - // Transfers to existing accounts, no commits - transfer_to_existing_accounts(&mut group, false); - - // Transfers to existing purses, no commits - transfer_to_existing_purses(&mut group, false); - - // Transfers to existing accounts, with commits - transfer_to_existing_accounts(&mut group, true); - - // Transfers to existing purses, with commits - transfer_to_existing_purses(&mut group, true); - - group.finish(); -} - -criterion_group!( - name = native_transfer_benches; - config = Criterion::default().with_measurement(WallTime); - targets = native_transfer_bench -); -criterion_group!( - name = benches; - config = Criterion::default().with_measurement(WallTime); - targets = transfer_bench -); -criterion_main!(benches, native_transfer_benches); diff --git a/execution_engine_testing/tests/bin/README.md b/execution_engine_testing/tests/bin/README.md deleted file mode 100644 index 6f3b75454f..0000000000 --- a/execution_engine_testing/tests/bin/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# `disk_use` binary - -A binary that will construct global state and profile the disk use of various operations. It's recommended to run this tool in `--release` mode. - -The outcome is a report, `disk_use_report.csv`. This contains time-series data with the following columns, with one line per block: - -- `height` - height of the simulated chain. -- `db-size` - size on disk of the backing trie database. -- `transfers` - total number of transfers run. -- `time_ms` - time in milliseconds for a given block to run. -- `necessary_tries` - calculated value for the number of tries we expect to find in the trie database. -- `total_tries` - found total number of tries in the backing trie database. - -This report can be used to get a relatively quick view into disk and time cost of running transfers and auction processes. - diff --git a/execution_engine_testing/tests/bin/disk_use.rs b/execution_engine_testing/tests/bin/disk_use.rs deleted file mode 100644 index b2f533e039..0000000000 --- a/execution_engine_testing/tests/bin/disk_use.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::{fs::File, io::BufWriter}; - -use casper_engine_test_support::auction::run_blocks_with_transfers_and_step; - -fn main() { - let purse_count = 100; - let total_transfer_count = 100; - let transfers_per_block = 1; - let block_count = total_transfer_count / transfers_per_block; - let delegator_count = 20_000; - let validator_count = 100; - - let report_writer = BufWriter::new(File::create("disk_use_report.csv").unwrap()); - run_blocks_with_transfers_and_step( - transfers_per_block, - purse_count, - true, - true, - block_count, - delegator_count, - validator_count, - report_writer, - ); -} diff --git a/execution_engine_testing/tests/src/lmdb_fixture.rs b/execution_engine_testing/tests/src/lmdb_fixture.rs index 9490b3a759..2260c6fd4f 100644 --- a/execution_engine_testing/tests/src/lmdb_fixture.rs +++ b/execution_engine_testing/tests/src/lmdb_fixture.rs @@ -36,7 +36,7 @@ pub(crate) fn is_fixture_generator_enabled() -> bool { /// This is a special place in the global state where fixture contains a registry. #[cfg(test)] -pub(crate) const CONTRACT_REGISTRY_SPECIAL_ADDRESS: Key = +pub(crate) const ENTRY_REGISTRY_SPECIAL_ADDRESS: Key = Key::URef(URef::new([0u8; 32], AccessRights::all())); fn path_to_lmdb_fixtures() -> PathBuf { @@ -88,6 +88,7 @@ pub fn builder_from_global_state_fixture( LmdbWasmTestBuilder::open( &path_to_gs, ChainspecConfig::default(), + lmdb_fixture_state.genesis_protocol_version(), lmdb_fixture_state.post_state_hash, ), lmdb_fixture_state, diff --git a/execution_engine_testing/tests/src/test/bulk_update_with_scratch_trie.rs b/execution_engine_testing/tests/src/test/bulk_update_with_scratch_trie.rs deleted file mode 100644 index 31d7346b67..0000000000 --- a/execution_engine_testing/tests/src/test/bulk_update_with_scratch_trie.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::{fs::File, io::BufWriter}; - -use casper_engine_test_support::auction::run_blocks_with_transfers_and_step; - -#[ignore] -#[test] -fn should_run_transfers_and_auction_producing_expected_number_of_tries_only() { - let purse_count = 100; - let total_transfer_count = 10; - let transfers_per_block = 1; - let block_count = total_transfer_count / transfers_per_block; - let delegator_count = 100; - let validator_count = 10; - - let report_writer = BufWriter::new(File::create("disk_use_report.csv").unwrap()); - run_blocks_with_transfers_and_step( - transfers_per_block, - purse_count, - true, - true, - block_count, - delegator_count, - validator_count, - report_writer, - ); -} diff --git a/execution_engine_testing/tests/src/test/chainspec_registry.rs b/execution_engine_testing/tests/src/test/chainspec_registry.rs index 8f00fd7fc0..e675064800 100644 --- a/execution_engine_testing/tests/src/test/chainspec_registry.rs +++ b/execution_engine_testing/tests/src/test/chainspec_registry.rs @@ -1,10 +1,9 @@ -use once_cell::sync::Lazy; use rand::Rng; use tempfile::TempDir; use casper_engine_test_support::{ LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_EXEC_CONFIG, DEFAULT_GENESIS_CONFIG_HASH, - DEFAULT_PROTOCOL_VERSION, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, }; use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ChainspecRegistry, Digest, EraId, Key, ProtocolVersion}; @@ -13,14 +12,12 @@ use crate::lmdb_fixture; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); #[ignore] #[test] @@ -35,8 +32,8 @@ fn should_commit_chainspec_registry_during_genesis() { ChainspecRegistry::new_with_genesis(&chainspec_bytes, &genesis_account); let run_genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, DEFAULT_EXEC_CONFIG.clone(), chainspec_registry, ); @@ -73,8 +70,8 @@ fn should_fail_to_commit_genesis_when_missing_genesis_accounts_hash() { ChainspecRegistry::new_with_optional_global_state(&chainspec_bytes, None); let run_genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, DEFAULT_EXEC_CONFIG.clone(), incomplete_chainspec_registry, ); @@ -99,7 +96,7 @@ fn should_upgrade_chainspec_registry(cfg: TestConfig) { builder } else { let mut builder = LmdbWasmTestBuilder::new(data_dir.path()); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder }; @@ -116,8 +113,8 @@ fn should_upgrade_chainspec_registry(cfg: TestConfig) { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .with_chainspec_registry(upgraded_chainspec_registry) .build() diff --git a/execution_engine_testing/tests/src/test/check_transfer_success.rs b/execution_engine_testing/tests/src/test/check_transfer_success.rs index 80d194330d..da90701b71 100644 --- a/execution_engine_testing/tests/src/test/check_transfer_success.rs +++ b/execution_engine_testing/tests/src/test/check_transfer_success.rs @@ -23,7 +23,7 @@ fn test_check_transfer_success_with_source_only() { // create a genesis account. let genesis_account = GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); @@ -32,8 +32,8 @@ fn test_check_transfer_success_with_source_only() { accounts.extend((*DEFAULT_ACCOUNTS).clone()); let genesis_config = create_genesis_config(accounts); let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -48,7 +48,7 @@ fn test_check_transfer_success_with_source_only() { // build the deploy. let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_session_code(path, session_args) .with_address(*DEFAULT_ACCOUNT_ADDR) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) @@ -56,7 +56,7 @@ fn test_check_transfer_success_with_source_only() { .build(); // build a request to execute the deploy. - let exec_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder.run_genesis(genesis_request).commit(); @@ -72,7 +72,7 @@ fn test_check_transfer_success_with_source_only() { builder.exec(exec_request).commit().expect_success(); let transaction_fee = builder.get_proposer_purse_balance() - proposer_starting_balance; - let expected_source_ending_balance = Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)) + let expected_source_ending_balance = Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE) - Motes::new(transfer_amount) - Motes::new(transaction_fee); let actual_source_ending_balance = Motes::new(builder.get_purse_balance(source_purse)); @@ -85,7 +85,7 @@ fn test_check_transfer_success_with_source_only() { fn test_check_transfer_success_with_source_only_errors() { let genesis_account = GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); @@ -93,8 +93,8 @@ fn test_check_transfer_success_with_source_only_errors() { accounts.extend((*DEFAULT_ACCOUNTS).clone()); let genesis_config = create_genesis_config(accounts); let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -111,14 +111,14 @@ fn test_check_transfer_success_with_source_only_errors() { }; let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_session_code(path, session_args) .with_address(*DEFAULT_ACCOUNT_ADDR) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) .build(); - let exec_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); // Set up test builder and run genesis. let mut builder = LmdbWasmTestBuilder::default(); @@ -133,7 +133,7 @@ fn test_check_transfer_success_with_source_only_errors() { builder.exec(exec_request).commit().expect_success(); let transaction_fee = builder.get_proposer_purse_balance() - proposer_starting_balance; - let expected_source_ending_balance = Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)) + let expected_source_ending_balance = Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE) - Motes::new(transfer_amount) - Motes::new(transaction_fee); let actual_source_ending_balance = Motes::new(builder.get_purse_balance(source_purse)); @@ -146,7 +146,7 @@ fn test_check_transfer_success_with_source_only_errors() { fn test_check_transfer_success_with_source_and_target() { let genesis_account = GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); @@ -154,8 +154,8 @@ fn test_check_transfer_success_with_source_and_target() { accounts.extend((*DEFAULT_ACCOUNTS).clone()); let genesis_config = create_genesis_config(accounts); let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -168,14 +168,14 @@ fn test_check_transfer_success_with_source_and_target() { ARG_AMOUNT => transfer_amount }; let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_session_code(path, session_args) .with_address(*DEFAULT_ACCOUNT_ADDR) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) .build(); - let exec_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder.run_genesis(genesis_request).commit(); @@ -191,7 +191,7 @@ fn test_check_transfer_success_with_source_and_target() { builder.exec(exec_request).commit().expect_success(); let transaction_fee = builder.get_proposer_purse_balance() - proposer_starting_balance; - let expected_source_ending_balance = Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)) + let expected_source_ending_balance = Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE) - Motes::new(transfer_amount) - Motes::new(transaction_fee); let actual_source_ending_balance = Motes::new(builder.get_purse_balance(source_purse)); diff --git a/execution_engine_testing/tests/src/test/contract_api/account/associated_keys.rs b/execution_engine_testing/tests/src/test/contract_api/account/associated_keys.rs index fbe7fe1ceb..86b62c066d 100644 --- a/execution_engine_testing/tests/src/test/contract_api/account/associated_keys.rs +++ b/execution_engine_testing/tests/src/test/contract_api/account/associated_keys.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, addressable_entity::Weight, runtime_args, U512}; @@ -34,9 +34,7 @@ fn should_manage_associated_key() { ) .build(); - builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) - .commit(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()).commit(); builder.exec(exec_request_1).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/contract_api/account/authorized_keys.rs b/execution_engine_testing/tests/src/test/contract_api/account/authorized_keys.rs index 4cb410d868..6b1d72896a 100644 --- a/execution_engine_testing/tests/src/test/contract_api/account/authorized_keys.rs +++ b/execution_engine_testing/tests/src/test/contract_api/account/authorized_keys.rs @@ -1,15 +1,13 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, + ARG_AMOUNT, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{ engine_state::{self, Error}, execution::ExecError, }; use casper_storage::{system::transfer::TransferError, tracking_copy::TrackingCopyError}; -use casper_types::{ - account::AccountHash, addressable_entity::Weight, runtime_args, system::mint, U512, -}; +use casper_types::{account::AccountHash, addressable_entity::Weight, runtime_args, U512}; const CONTRACT_ADD_ASSOCIATED_KEY: &str = "add_associated_key.wasm"; const CONTRACT_ADD_UPDATE_ASSOCIATED_KEY: &str = "add_update_associated_key.wasm"; @@ -37,7 +35,7 @@ fn should_deploy_with_authorized_identity_key() { .build(); // Basic deploy with single key LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .expect_success(); @@ -50,43 +48,38 @@ fn should_raise_auth_failure_with_invalid_key() { // Error::Authorization assert_ne!(*DEFAULT_ACCOUNT_ADDR, KEY_1); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), - ARG_DEPLOY_THRESHOLD => Weight::new(1) - }, - ) - .with_deploy_hash([1u8; 32]) - .with_authorization_keys(&[KEY_1]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), + ARG_DEPLOY_THRESHOLD => Weight::new(1) + }, + ) + .with_deploy_hash([1u8; 32]) + .with_authorization_keys(&[KEY_1]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // Basic deploy with single key let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!( deploy_result.has_precondition_failure(), "{:?}", deploy_result ); - let message = format!("{}", deploy_result.as_error().unwrap()); + let message = format!("{}", deploy_result.error().unwrap()); assert_eq!( message, @@ -106,39 +99,34 @@ fn should_raise_auth_failure_with_invalid_keys() { assert_ne!(*DEFAULT_ACCOUNT_ADDR, KEY_2); assert_ne!(*DEFAULT_ACCOUNT_ADDR, KEY_3); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), - ARG_DEPLOY_THRESHOLD => Weight::new(1) - }, - ) - .with_deploy_hash([1u8; 32]) - .with_authorization_keys(&[KEY_2, KEY_1, KEY_3]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), + ARG_DEPLOY_THRESHOLD => Weight::new(1) + }, + ) + .with_deploy_hash([1u8; 32]) + .with_authorization_keys(&[KEY_2, KEY_1, KEY_3]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // Basic deploy with single key let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!(deploy_result.has_precondition_failure()); - let message = format!("{}", deploy_result.as_error().unwrap()); + let message = format!("{}", deploy_result.error().unwrap()); assert_eq!( message, @@ -192,7 +180,7 @@ fn should_raise_deploy_authorization_failure() { // Basic deploy with single key let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) // Reusing a test contract that would add new key .exec(exec_request_1) .expect_success() @@ -209,23 +197,21 @@ fn should_raise_deploy_authorization_failure() { .expect_success() .commit(); - let exec_request_5 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - // Next deploy will see deploy threshold == 4, keymgmnt == 5 - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(5), - ARG_DEPLOY_THRESHOLD => Weight::new(4) - }, //args - ) - .with_deploy_hash([5u8; 32]) - .with_authorization_keys(&[KEY_1]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + // Next deploy will see deploy threshold == 4, keymgmnt == 5 + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(5), + ARG_DEPLOY_THRESHOLD => Weight::new(4) + }, //args + ) + .with_deploy_hash([5u8; 32]) + .with_authorization_keys(&[KEY_1]) + .build(); + let exec_request_5 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // With deploy threshold == 3 using single secondary key // with weight == 2 should raise deploy authorization failure. @@ -234,32 +220,27 @@ fn should_raise_deploy_authorization_failure() { { let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!(deploy_result.has_precondition_failure()); - let message = format!("{}", deploy_result.as_error().unwrap()); + let message = format!("{}", deploy_result.error().unwrap()); assert!(message.contains(&format!("{}", ExecError::DeploymentAuthorizationFailure))) } - let exec_request_6 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - // change deployment threshold to 4 - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(6), - ARG_DEPLOY_THRESHOLD => Weight::new(5) - }, - ) - .with_deploy_hash([6u8; 32]) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, KEY_1, KEY_2, KEY_3]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + // change deployment threshold to 4 + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(6), + ARG_DEPLOY_THRESHOLD => Weight::new(5) + }, + ) + .with_deploy_hash([6u8; 32]) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, KEY_1, KEY_2, KEY_3]) + .build(); + let exec_request_6 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // identity key (w: 1) and KEY_1 (w: 2) passes threshold of 3 builder .clear_results() @@ -267,23 +248,21 @@ fn should_raise_deploy_authorization_failure() { .expect_success() .commit(); - let exec_request_7 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - // change deployment threshold to 4 - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), - ARG_DEPLOY_THRESHOLD => Weight::new(0) - }, //args - ) - .with_deploy_hash([6u8; 32]) - .with_authorization_keys(&[KEY_2, KEY_1]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + // change deployment threshold to 4 + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), + ARG_DEPLOY_THRESHOLD => Weight::new(0) + }, //args + ) + .with_deploy_hash([6u8; 32]) + .with_authorization_keys(&[KEY_2, KEY_1]) + .build(); + let exec_request_7 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // deployment threshold is now 4 // failure: KEY_2 weight + KEY_1 weight < deployment threshold @@ -293,33 +272,28 @@ fn should_raise_deploy_authorization_failure() { { let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!(deploy_result.has_precondition_failure()); - let message = format!("{}", deploy_result.as_error().unwrap()); + let message = format!("{}", deploy_result.error().unwrap()); assert!(message.contains(&format!("{}", ExecError::DeploymentAuthorizationFailure))) } - let exec_request_8 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - // change deployment threshold to 4 - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), - ARG_DEPLOY_THRESHOLD => Weight::new(0) - }, //args - ) - .with_deploy_hash([8u8; 32]) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, KEY_1, KEY_2, KEY_3]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + // change deployment threshold to 4 + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), + ARG_DEPLOY_THRESHOLD => Weight::new(0) + }, //args + ) + .with_deploy_hash([8u8; 32]) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, KEY_1, KEY_2, KEY_3]) + .build(); + let exec_request_8 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); // success: identity key weight + KEY_1 weight + KEY_2 weight >= deployment // threshold @@ -353,7 +327,7 @@ fn should_authorize_deploy_with_multiple_keys() { // Basic deploy with single key let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) // Reusing a test contract that would add new key .exec(exec_request_1) .expect_success() @@ -364,22 +338,20 @@ fn should_authorize_deploy_with_multiple_keys() { // KEY_1 (w: 2) KEY_2 (w: 2) each passes default threshold of 1 - let exec_request_3 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), - ARG_DEPLOY_THRESHOLD => Weight::new(0), - }, - ) - .with_deploy_hash([36; 32]) - .with_authorization_keys(&[KEY_2, KEY_1]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), + ARG_DEPLOY_THRESHOLD => Weight::new(0), + }, + ) + .with_deploy_hash([36; 32]) + .with_authorization_keys(&[KEY_2, KEY_1]) + .build(); + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); builder.exec(exec_request_3).expect_success().commit(); } @@ -420,7 +392,7 @@ fn should_not_authorize_deploy_with_duplicated_keys() { .build(); // Basic deploy with single key let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder // Reusing a test contract that would add new key @@ -432,40 +404,35 @@ fn should_not_authorize_deploy_with_duplicated_keys() { builder.exec(exec_request_3).expect_success().commit(); - let exec_request_3 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT, - }) - .with_session_code( - CONTRACT_SET_ACTION_THRESHOLDS, - runtime_args! { - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), - ARG_DEPLOY_THRESHOLD => Weight::new(0) - }, - ) - .with_deploy_hash([3u8; 32]) - .with_authorization_keys(&[ - KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, - ]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT, + }) + .with_session_code( + CONTRACT_SET_ACTION_THRESHOLDS, + runtime_args! { + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), + ARG_DEPLOY_THRESHOLD => Weight::new(0) + }, + ) + .with_deploy_hash([3u8; 32]) + .with_authorization_keys(&[ + KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, KEY_1, + ]) + .build(); + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); builder.clear_results().exec(exec_request_3).commit(); let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!( deploy_result.has_precondition_failure(), "{:?}", deploy_result ); - let message = format!("{}", deploy_result.as_error().unwrap()); + let message = format!("{}", deploy_result.error().unwrap()); assert!(message.contains(&format!( "{}", TrackingCopyError::DeploymentAuthorizationFailure @@ -508,7 +475,7 @@ fn should_not_authorize_transfer_without_deploy_key_threshold() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) // Reusing a test contract that would add new key .exec(add_key_1_request) .expect_success() @@ -522,32 +489,16 @@ fn should_not_authorize_transfer_without_deploy_key_threshold() { .commit(); // KEY_1 (w: 2) DEFAULT_ACCOUNT (w: 1) does not pass deploy threshold of 5 - let id: Option = None; - - let transfer_request_1 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_transfer_args(runtime_args! { - mint::ARG_TARGET => KEY_2, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => id, - }) - .with_deploy_hash([36; 32]) - .with_authorization_keys(&[KEY_1, *DEFAULT_ACCOUNT_ADDR]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; - - builder.exec(transfer_request_1).commit(); + let transfer_request_1 = TransferRequestBuilder::new(transfer_amount, KEY_2) + .with_authorization_keys([KEY_1, *DEFAULT_ACCOUNT_ADDR]) + .build(); + + builder.transfer_and_commit(transfer_request_1); let response = builder .get_exec_result_owned(3) - .expect("should have response") - .first() - .cloned() - .expect("should have first result"); - let error = response.as_error().expect("should have error"); + .expect("should have response"); + let error = response.error().expect("should have error"); assert!(matches!( error, Error::Transfer(TransferError::TrackingCopy( @@ -556,22 +507,11 @@ fn should_not_authorize_transfer_without_deploy_key_threshold() { )); // KEY_1 (w: 2) KEY_2 (w: 2) DEFAULT_ACCOUNT_ADDR (w: 1) each passes threshold of 5 - let id: Option = None; - - let transfer_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_transfer_args(runtime_args! { - mint::ARG_TARGET => KEY_2, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => id, - }) - .with_deploy_hash([37; 32]) - .with_authorization_keys(&[KEY_2, KEY_1, *DEFAULT_ACCOUNT_ADDR]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; - - builder.exec(transfer_request).expect_success().commit(); + let transfer_request = TransferRequestBuilder::new(transfer_amount, KEY_2) + .with_authorization_keys([KEY_2, KEY_1, *DEFAULT_ACCOUNT_ADDR]) + .build(); + + builder + .transfer_and_commit(transfer_request) + .expect_success(); } diff --git a/execution_engine_testing/tests/src/test/contract_api/account/key_management_thresholds.rs b/execution_engine_testing/tests/src/test/contract_api/account/key_management_thresholds.rs index 3d43f5f3bb..ee2e8f734b 100644 --- a/execution_engine_testing/tests/src/test/contract_api/account/key_management_thresholds.rs +++ b/execution_engine_testing/tests/src/test/contract_api/account/key_management_thresholds.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args}; @@ -24,7 +24,7 @@ fn should_verify_key_management_permission_with_low_weight() { ) .build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() @@ -42,26 +42,24 @@ fn should_verify_key_management_permission_with_sufficient_weight() { runtime_args! { ARG_STAGE => String::from("init") }, ) .build(); - let exec_request_2 = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - // This test verifies that all key management operations succeed - .with_session_code( - "key_management_thresholds.wasm", - runtime_args! { ARG_STAGE => String::from("test-key-mgmnt-succeed") }, - ) - .with_deploy_hash([2u8; 32]) - .with_authorization_keys(&[ - *DEFAULT_ACCOUNT_ADDR, - // Key [42; 32] is created in init stage - AccountHash::new([42; 32]), - ]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + // This test verifies that all key management operations succeed + .with_session_code( + "key_management_thresholds.wasm", + runtime_args! { ARG_STAGE => String::from("test-key-mgmnt-succeed") }, + ) + .with_deploy_hash([2u8; 32]) + .with_authorization_keys(&[ + *DEFAULT_ACCOUNT_ADDR, + // Key [42; 32] is created in init stage + AccountHash::new([42; 32]), + ]) + .build(); + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() diff --git a/execution_engine_testing/tests/src/test/contract_api/account/named_keys.rs b/execution_engine_testing/tests/src/test/contract_api/account/named_keys.rs index 1a03dd35a8..7098b23c19 100644 --- a/execution_engine_testing/tests/src/test/contract_api/account/named_keys.rs +++ b/execution_engine_testing/tests/src/test/contract_api/account/named_keys.rs @@ -1,8 +1,7 @@ use std::convert::TryFrom; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{bytesrepr::FromBytes, runtime_args, CLTyped, CLValue, Key, U512}; @@ -44,7 +43,7 @@ fn read_value(builder: &mut LmdbWasmTestBuilder, key: Ke fn should_run_named_keys_contract() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); run_command(&mut builder, COMMAND_CREATE_UREF1); diff --git a/execution_engine_testing/tests/src/test/contract_api/account/named_keys_stored.rs b/execution_engine_testing/tests/src/test/contract_api/account/named_keys_stored.rs index 17cf9b4847..2fc1c1fd8d 100644 --- a/execution_engine_testing/tests/src/test/contract_api/account/named_keys_stored.rs +++ b/execution_engine_testing/tests/src/test/contract_api/account/named_keys_stored.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::execution::ExecError; use casper_types::{runtime_args, ApiError, RuntimeArgs}; @@ -95,7 +94,7 @@ fn should_run_stored_named_keys_module_bytes_to_contract_to_contract() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, "named_keys_stored.wasm", diff --git a/execution_engine_testing/tests/src/test/contract_api/add_contract_version.rs b/execution_engine_testing/tests/src/test/contract_api/add_contract_version.rs new file mode 100644 index 0000000000..0c68dd8218 --- /dev/null +++ b/execution_engine_testing/tests/src/test/contract_api/add_contract_version.rs @@ -0,0 +1,79 @@ +use casper_engine_test_support::{ + utils, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, + DEFAULT_ACCOUNT_SECRET_KEY, LOCAL_GENESIS_REQUEST, +}; +use casper_execution_engine::{engine_state::Error as StateError, execution::ExecError}; +use casper_types::{ + ApiError, BlockTime, RuntimeArgs, Transaction, TransactionSessionKind, TransactionV1Builder, +}; + +const CONTRACT: &str = "do_nothing_stored.wasm"; +const ENTRY_POINT: &str = "call"; +const CHAIN_NAME: &str = "a"; +const BLOCK_TIME: BlockTime = BlockTime::new(10); + +#[ignore] +#[test] +fn should_allow_add_contract_version_via_deploy() { + let mut builder = LmdbWasmTestBuilder::default(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()).commit(); + + let deploy_request = + ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, CONTRACT, RuntimeArgs::new()) + .build(); + + builder.exec(deploy_request).expect_success().commit(); +} + +fn try_add_contract_version(kind: TransactionSessionKind, should_succeed: bool) { + let mut builder = LmdbWasmTestBuilder::default(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()).commit(); + + let module_bytes = utils::read_wasm_file(CONTRACT); + + let txn = Transaction::from( + TransactionV1Builder::new_session(kind, module_bytes, ENTRY_POINT) + .with_secret_key(&DEFAULT_ACCOUNT_SECRET_KEY) + .with_chain_name(CHAIN_NAME) + .build() + .unwrap(), + ); + + let txn_request = ExecuteRequestBuilder::from_transaction(&txn) + .with_block_time(BLOCK_TIME) + .build(); + + builder.exec(txn_request); + + if should_succeed { + builder.expect_success(); + } else { + builder.assert_error(StateError::Exec(ExecError::Revert( + ApiError::NotAllowedToAddContractVersion, + ))) + } +} + +#[ignore] +#[test] +fn should_allow_add_contract_version_via_transaction_v1_installer() { + try_add_contract_version(TransactionSessionKind::Installer, true) +} + +#[ignore] +#[test] +fn should_allow_add_contract_version_via_transaction_v1_upgrader() { + try_add_contract_version(TransactionSessionKind::Upgrader, true) +} + +#[ignore] +#[test] +fn should_disallow_add_contract_version_via_transaction_v1_standard() { + try_add_contract_version(TransactionSessionKind::Standard, false) +} + +#[ignore] +#[test] +fn should_disallow_add_contract_version_via_transaction_v1_isolated() { + try_add_contract_version(TransactionSessionKind::Isolated, false) +} diff --git a/execution_engine_testing/tests/src/test/contract_api/create_purse.rs b/execution_engine_testing/tests/src/test/contract_api/create_purse.rs index b28c7eceb3..1abb7fadad 100644 --- a/execution_engine_testing/tests/src/test/contract_api/create_purse.rs +++ b/execution_engine_testing/tests/src/test/contract_api/create_purse.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args, U512}; @@ -33,7 +33,7 @@ fn should_insert_account_into_named_keys() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -67,7 +67,7 @@ fn should_create_usable_purse() { .build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() diff --git a/execution_engine_testing/tests/src/test/contract_api/dictionary.rs b/execution_engine_testing/tests/src/test/contract_api/dictionary.rs index 04e2ac88ec..a0bb96553c 100644 --- a/execution_engine_testing/tests/src/test/contract_api/dictionary.rs +++ b/execution_engine_testing/tests/src/test/contract_api/dictionary.rs @@ -1,18 +1,19 @@ +use std::{convert::TryFrom, path::PathBuf}; + use casper_engine_test_support::{ utils::create_genesis_config, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, - ARG_AMOUNT, DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, - DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_CHAINSPEC_REGISTRY, DEFAULT_GENESIS_CONFIG_HASH, - DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, + TransferRequestBuilder, ARG_AMOUNT, DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, + DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_CHAINSPEC_REGISTRY, + DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state::Error as EngineError, execution::ExecError}; use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ - account::AccountHash, addressable_entity::EntityKindTag, runtime_args, system::mint, - AccessRights, AddressableEntityHash, ApiError, CLType, CLValue, GenesisAccount, Key, Motes, - RuntimeArgs, StoredValue, U512, + account::AccountHash, addressable_entity::EntityKindTag, runtime_args, AccessRights, + AddressableEntityHash, ApiError, CLType, CLValue, GenesisAccount, Key, Motes, RuntimeArgs, + StoredValue, }; -use std::{convert::TryFrom, path::PathBuf}; use dictionary_call::{NEW_DICTIONARY_ITEM_KEY, NEW_DICTIONARY_VALUE}; @@ -26,17 +27,10 @@ const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); fn setup() -> (LmdbWasmTestBuilder, AddressableEntityHash) { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR).build(); let install_contract_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -45,7 +39,7 @@ fn setup() -> (LmdbWasmTestBuilder, AddressableEntityHash) { ) .build(); - builder.exec(fund_request).commit().expect_success(); + builder.transfer_and_commit(fund_request).expect_success(); builder .exec(install_contract_request) @@ -114,7 +108,7 @@ fn query_dictionary_item( _ => { return Err( "Provided base key is nether an account or a contract".to_string() - ) + ); } }; @@ -234,9 +228,8 @@ fn should_not_write_with_read_access_rights() { builder.exec(call_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -286,10 +279,8 @@ fn should_not_read_with_write_access_rights() { builder.exec(call_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -367,9 +358,8 @@ fn should_not_write_with_forged_uref() { builder.exec(call_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -405,9 +395,8 @@ fn should_fail_put_with_invalid_dictionary_item_key() { .build(); builder.exec(call_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -442,9 +431,8 @@ fn should_fail_get_with_invalid_dictionary_item_key() { .build(); builder.exec(call_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -460,17 +448,10 @@ fn should_fail_get_with_invalid_dictionary_item_key() { fn dictionary_put_should_fail_with_large_item_key() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR).build(); let install_contract_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -481,11 +462,10 @@ fn dictionary_put_should_fail_with_large_item_key() { ) .build(); - builder.exec(fund_request).commit().expect_success(); + builder.transfer_and_commit(fund_request).expect_success(); builder.exec(install_contract_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -501,17 +481,10 @@ fn dictionary_put_should_fail_with_large_item_key() { fn dictionary_get_should_fail_with_large_item_key() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR).build(); let install_contract_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -522,11 +495,10 @@ fn dictionary_get_should_fail_with_large_item_key() { ) .build(); - builder.exec(fund_request).commit().expect_success(); + builder.transfer_and_commit(fund_request).expect_success(); builder.exec(install_contract_request).commit(); - let exec_results = builder.get_last_exec_result().expect("should have results"); - assert_eq!(exec_results.len(), 1); - let error = exec_results[0].as_error().expect("should have error"); + let exec_result = builder.get_last_exec_result().expect("should have results"); + let error = exec_result.error().expect("should have error"); assert!( matches!( error, @@ -542,7 +514,7 @@ fn dictionary_get_should_fail_with_large_item_key() { fn should_query_dictionary_items_with_test_builder() { let genesis_account = GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); @@ -550,22 +522,22 @@ fn should_query_dictionary_items_with_test_builder() { accounts.extend((*DEFAULT_ACCOUNTS).clone()); let genesis_config = create_genesis_config(accounts); let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); let dictionary_code = PathBuf::from(DICTIONARY_WASM); let deploy_item = DeployItemBuilder::new() - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_session_code(dictionary_code, RuntimeArgs::new()) .with_address(*DEFAULT_ACCOUNT_ADDR) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) .build(); - let exec_request = ExecuteRequestBuilder::from_deploy_item(deploy_item).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder.run_genesis(genesis_request).commit(); @@ -664,7 +636,7 @@ fn should_query_dictionary_items_with_test_builder() { #[test] fn should_be_able_to_perform_dictionary_read() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let dictionary_session_call = ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, DICTIONARY_READ, RuntimeArgs::new()) @@ -680,7 +652,7 @@ fn should_be_able_to_perform_dictionary_read() { #[test] fn should_be_able_to_perform_read_from_key() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let read_from_key_session_call = ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, READ_FROM_KEY, RuntimeArgs::new()) diff --git a/execution_engine_testing/tests/src/test/contract_api/get_arg.rs b/execution_engine_testing/tests/src/test/contract_api/get_arg.rs index ad548a0710..112f0fc9a5 100644 --- a/execution_engine_testing/tests/src/test/contract_api/get_arg.rs +++ b/execution_engine_testing/tests/src/test/contract_api/get_arg.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - utils, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, ApiError, RuntimeArgs, U512}; @@ -17,7 +16,7 @@ fn call_get_arg(args: RuntimeArgs) -> Result<(), String> { ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, CONTRACT_GET_ARG, args).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); @@ -25,11 +24,7 @@ fn call_get_arg(args: RuntimeArgs) -> Result<(), String> { return Ok(()); } - let response = builder - .get_exec_result_owned(0) - .expect("should have a response"); - - let error_message = utils::get_error_message(response); + let error_message = builder.get_error_message().expect("should have a result"); Err(error_message) } diff --git a/execution_engine_testing/tests/src/test/contract_api/get_blocktime.rs b/execution_engine_testing/tests/src/test/contract_api/get_blocktime.rs index 033897ba20..0b65a29dca 100644 --- a/execution_engine_testing/tests/src/test/contract_api/get_blocktime.rs +++ b/execution_engine_testing/tests/src/test/contract_api/get_blocktime.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::runtime_args; @@ -20,7 +19,7 @@ fn should_run_get_blocktime_contract() { .with_block_time(block_time) .build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .expect_success(); diff --git a/execution_engine_testing/tests/src/test/contract_api/get_call_stack.rs b/execution_engine_testing/tests/src/test/contract_api/get_call_stack.rs index f2c9609057..70220c6e54 100644 --- a/execution_engine_testing/tests/src/test/contract_api/get_call_stack.rs +++ b/execution_engine_testing/tests/src/test/contract_api/get_call_stack.rs @@ -1,10 +1,7 @@ use num_traits::One; -use casper_engine_test_support::{LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR}; -use casper_execution_engine::{ - engine_state::{Error as CoreError, ExecuteRequest}, - execution::ExecError, -}; +use casper_engine_test_support::{ExecuteRequest, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR}; +use casper_execution_engine::{engine_state::Error as CoreError, execution::ExecError}; use casper_types::{ addressable_entity::NamedKeys, system::Caller, AddressableEntity, AddressableEntityHash, CLValue, EntityAddr, EntryPointType, HashAddr, Key, PackageAddr, PackageHash, StoredValue, @@ -35,7 +32,7 @@ fn stored_session(contract_hash: AddressableEntityHash) -> Call { Call { contract_address: ContractAddress::ContractHash(contract_hash), target_method: CONTRACT_FORWARDER_ENTRYPOINT_SESSION.to_string(), - entry_point_type: EntryPointType::Session, + entry_point_type: EntryPointType::Caller, } } @@ -43,7 +40,7 @@ fn stored_versioned_session(contract_package_hash: PackageHash) -> Call { Call { contract_address: ContractAddress::ContractPackageHash(contract_package_hash), target_method: CONTRACT_FORWARDER_ENTRYPOINT_SESSION.to_string(), - entry_point_type: EntryPointType::Session, + entry_point_type: EntryPointType::Caller, } } @@ -51,7 +48,7 @@ fn stored_contract(contract_hash: AddressableEntityHash) -> Call { Call { contract_address: ContractAddress::ContractHash(contract_hash), target_method: CONTRACT_FORWARDER_ENTRYPOINT_CONTRACT.to_string(), - entry_point_type: EntryPointType::AddressableEntity, + entry_point_type: EntryPointType::Called, } } @@ -59,7 +56,7 @@ fn stored_versioned_contract(contract_package_hash: PackageHash) -> Call { Call { contract_address: ContractAddress::ContractPackageHash(contract_package_hash), target_method: CONTRACT_FORWARDER_ENTRYPOINT_CONTRACT.to_string(), - entry_point_type: EntryPointType::AddressableEntity, + entry_point_type: EntryPointType::Called, } } @@ -174,7 +171,7 @@ impl BuilderExt for LmdbWasmTestBuilder { let current_entity_hash = package.current_entity_hash().unwrap(); let current_contract_entity_key = - EntityAddr::new_contract_entity_addr(current_entity_hash.value()); + EntityAddr::new_smart_contract(current_entity_hash.value()); let cl_value = self .query( @@ -212,12 +209,12 @@ fn assert_each_context_has_correct_call_stack_info( let stored_call_stack_key = format!("call_stack-{}", i); // we need to know where to look for the call stack information let call_stack = match call.entry_point_type { - EntryPointType::AddressableEntity | EntryPointType::Factory => builder + EntryPointType::Called | EntryPointType::Factory => builder .get_call_stack_from_contract_context( &stored_call_stack_key, current_contract_package_hash, ), - EntryPointType::Session => { + EntryPointType::Caller => { builder.get_call_stack_from_session_context(&stored_call_stack_key) } }; @@ -233,7 +230,7 @@ fn assert_each_context_has_correct_call_stack_info( assert_eq!( head, - [Caller::Session { + [Caller::Initiator { account_hash: *DEFAULT_ACCOUNT_ADDR, }], ); @@ -263,7 +260,7 @@ fn assert_each_context_has_correct_call_stack_info_module_bytes( let (head, _) = call_stack.split_at(usize::one()); assert_eq!( head, - [Caller::Session { + [Caller::Initiator { account_hash: *DEFAULT_ACCOUNT_ADDR, }], ); @@ -272,19 +269,19 @@ fn assert_each_context_has_correct_call_stack_info_module_bytes( let stored_call_stack_key = format!("call_stack-{}", i); // we need to know where to look for the call stack information let call_stack = match call.entry_point_type { - EntryPointType::AddressableEntity | EntryPointType::Factory => builder + EntryPointType::Called | EntryPointType::Factory => builder .get_call_stack_from_contract_context( &stored_call_stack_key, current_contract_package_hash.value(), ), - EntryPointType::Session => { + EntryPointType::Caller => { builder.get_call_stack_from_session_context(&stored_call_stack_key) } }; let (head, rest) = call_stack.split_at(usize::one()); assert_eq!( head, - [Caller::Session { + [Caller::Initiator { account_hash: *DEFAULT_ACCOUNT_ADDR, }], ); @@ -296,7 +293,7 @@ fn assert_call_stack_matches_calls(call_stack: Vec, calls: &[Call]) { for (index, expected_call_stack_element) in call_stack.iter().enumerate() { let maybe_call = calls.get(index); match (maybe_call, expected_call_stack_element) { - // Versioned Call with EntryPointType::Contract + // Versioned Call with EntryPointType::Called ( Some(Call { entry_point_type, @@ -304,25 +301,25 @@ fn assert_call_stack_matches_calls(call_stack: Vec, calls: &[Call]) { ContractAddress::ContractPackageHash(current_contract_package_hash), .. }), - Caller::AddressableEntity { + Caller::Entity { package_hash: contract_package_hash, .. }, - ) if *entry_point_type == EntryPointType::AddressableEntity + ) if *entry_point_type == EntryPointType::Called && *contract_package_hash == *current_contract_package_hash => {} - // Unversioned Call with EntryPointType::Contract + // Unversioned Call with EntryPointType::Called ( Some(Call { entry_point_type, contract_address: ContractAddress::ContractHash(current_contract_hash), .. }), - Caller::AddressableEntity { + Caller::Entity { entity_hash: contract_hash, .. }, - ) if *entry_point_type == EntryPointType::AddressableEntity + ) if *entry_point_type == EntryPointType::Called && *contract_hash == *current_contract_hash => {} _ => panic!( @@ -3137,24 +3134,22 @@ mod payment { const DEPTHS: &[usize] = &[0, 6, 10]; fn execute(builder: &mut LmdbWasmTestBuilder, call_depth: usize, subcalls: Vec) { - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let sender = *DEFAULT_ACCOUNT_ADDR; - let args = runtime_args! { - ARG_CALLS => subcalls, - ARG_CURRENT_DEPTH => 0u8, - mint::ARG_AMOUNT => approved_amount(call_depth), - }; - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_payment_code(CONTRACT_CALL_RECURSIVE_SUBCALL, args) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + let sender = *DEFAULT_ACCOUNT_ADDR; + let args = runtime_args! { + ARG_CALLS => subcalls, + ARG_CURRENT_DEPTH => 0u8, + mint::ARG_AMOUNT => approved_amount(call_depth), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_payment_code(CONTRACT_CALL_RECURSIVE_SUBCALL, args) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); super::execute_and_assert_result( call_depth, @@ -3169,34 +3164,32 @@ mod payment { call_depth: usize, subcalls: Vec, ) { - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let sender = *DEFAULT_ACCOUNT_ADDR; - - let args = runtime_args! { - ARG_CALLS => subcalls, - ARG_CURRENT_DEPTH => 0u8, - mint::ARG_AMOUNT => approved_amount(call_depth), - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_versioned_payment_contract_by_name( - CONTRACT_PACKAGE_NAME, - None, - CONTRACT_FORWARDER_ENTRYPOINT_SESSION, - args, - ) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + + let sender = *DEFAULT_ACCOUNT_ADDR; + + let args = runtime_args! { + ARG_CALLS => subcalls, + ARG_CURRENT_DEPTH => 0u8, + mint::ARG_AMOUNT => approved_amount(call_depth), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_versioned_payment_contract_by_name( + CONTRACT_PACKAGE_NAME, + None, + CONTRACT_FORWARDER_ENTRYPOINT_SESSION, + args, + ) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + super::execute_and_assert_result( call_depth, builder, @@ -3211,29 +3204,27 @@ mod payment { subcalls: Vec, current_contract_package_hash: HashAddr, ) { - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let sender = *DEFAULT_ACCOUNT_ADDR; - let args = runtime_args! { - ARG_CALLS => subcalls, - ARG_CURRENT_DEPTH => 0u8, - mint::ARG_AMOUNT => approved_amount(call_depth), - }; - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_versioned_payment_contract_by_hash( - current_contract_package_hash, - None, - CONTRACT_FORWARDER_ENTRYPOINT_SESSION, - args, - ) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + let sender = *DEFAULT_ACCOUNT_ADDR; + let args = runtime_args! { + ARG_CALLS => subcalls, + ARG_CURRENT_DEPTH => 0u8, + mint::ARG_AMOUNT => approved_amount(call_depth), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_versioned_payment_contract_by_hash( + current_contract_package_hash, + None, + CONTRACT_FORWARDER_ENTRYPOINT_SESSION, + args, + ) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); super::execute_and_assert_result( call_depth, @@ -3248,33 +3239,31 @@ mod payment { call_depth: usize, subcalls: Vec, ) { - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - - let sender = *DEFAULT_ACCOUNT_ADDR; - - let args = runtime_args! { - ARG_CALLS => subcalls, - ARG_CURRENT_DEPTH => 0u8, - mint::ARG_AMOUNT => approved_amount(call_depth), - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_payment_named_key( - CONTRACT_NAME, - CONTRACT_FORWARDER_ENTRYPOINT_SESSION, - args, - ) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + + let sender = *DEFAULT_ACCOUNT_ADDR; + + let args = runtime_args! { + ARG_CALLS => subcalls, + ARG_CURRENT_DEPTH => 0u8, + mint::ARG_AMOUNT => approved_amount(call_depth), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_payment_named_key( + CONTRACT_NAME, + CONTRACT_FORWARDER_ENTRYPOINT_SESSION, + args, + ) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + super::execute_and_assert_result( call_depth, builder, @@ -3289,28 +3278,26 @@ mod payment { subcalls: Vec, current_contract_hash: HashAddr, ) { - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let sender = *DEFAULT_ACCOUNT_ADDR; - let args = runtime_args! { - ARG_CALLS => subcalls, - ARG_CURRENT_DEPTH => 0u8, - mint::ARG_AMOUNT => approved_amount(call_depth), - }; - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_payment_hash( - current_contract_hash.into(), - CONTRACT_FORWARDER_ENTRYPOINT_SESSION, - args, - ) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + let sender = *DEFAULT_ACCOUNT_ADDR; + let args = runtime_args! { + ARG_CALLS => subcalls, + ARG_CURRENT_DEPTH => 0u8, + mint::ARG_AMOUNT => approved_amount(call_depth), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_payment_hash( + current_contract_hash.into(), + CONTRACT_FORWARDER_ENTRYPOINT_SESSION, + args, + ) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let is_entry_point_type_session = true; @@ -3585,7 +3572,7 @@ mod payment { // Stored session + recursive subcall #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_versioned_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3610,7 +3597,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_versioned_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3639,7 +3626,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3659,7 +3646,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3687,7 +3674,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_versioned_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3712,7 +3699,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_hash_to_stored_versioned_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3744,7 +3731,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3764,7 +3751,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_hash_to_stored_session() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3789,7 +3776,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_versioned_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3814,7 +3801,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_versioned_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3844,7 +3831,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3864,7 +3851,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3892,7 +3879,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_versioned_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3916,7 +3903,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_hash_to_stored_versioned_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3948,7 +3935,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_contract() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -3968,6 +3955,7 @@ mod payment { } #[ignore] + #[allow(unused)] #[test] fn stored_payment_by_hash_to_stored_contract() { for call_depth in DEPTHS { @@ -3995,7 +3983,7 @@ mod payment { // Stored session + recursive subcall failure cases #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_versioned_contract_to_stored_versioned_session_should_fail( ) { for call_depth in DEPTHS { @@ -4026,7 +4014,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_versioned_contract_to_stored_session_should_fail() { for call_depth in DEPTHS { @@ -4062,7 +4050,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_name_to_stored_contract_to_stored_versioned_session_should_fail() { for call_depth in DEPTHS { @@ -4094,7 +4082,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_versioned_payment_by_hash_to_stored_contract_to_stored_session_should_fail() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -4128,7 +4116,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_versioned_contract_to_stored_versioned_session_should_fail() { for call_depth in DEPTHS { @@ -4159,7 +4147,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_session_by_hash_to_stored_versioned_contract_to_stored_session_should_fail() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -4194,7 +4182,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_contract_to_stored_versioned_session_should_fail() { for call_depth in DEPTHS { let mut builder = super::setup(); @@ -4225,7 +4213,7 @@ mod payment { } #[ignore] - #[test] + #[allow(unused)] fn stored_payment_by_name_to_stored_contract_to_stored_session_should_fail() { for call_depth in DEPTHS { let mut builder = super::setup(); diff --git a/execution_engine_testing/tests/src/test/contract_api/get_caller.rs b/execution_engine_testing/tests/src/test/contract_api/get_caller.rs index 2f0d2b8e1c..7e369eb846 100644 --- a/execution_engine_testing/tests/src/test/contract_api/get_caller.rs +++ b/execution_engine_testing/tests/src/test/contract_api/get_caller.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args}; @@ -13,7 +13,7 @@ const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); #[test] fn should_run_get_caller_contract() { LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec( ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -31,7 +31,7 @@ fn should_run_get_caller_contract() { fn should_run_get_caller_contract_other_account() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec( @@ -63,7 +63,7 @@ fn should_run_get_caller_contract_other_account() { fn should_run_get_caller_subcall_contract() { { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec( @@ -80,7 +80,7 @@ fn should_run_get_caller_subcall_contract() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec( ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/contract_api/get_phase.rs b/execution_engine_testing/tests/src/test/contract_api/get_phase.rs index 578257c57f..e433d7479c 100644 --- a/execution_engine_testing/tests/src/test/contract_api/get_phase.rs +++ b/execution_engine_testing/tests/src/test/contract_api/get_phase.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, Phase}; @@ -12,29 +12,27 @@ const ARG_AMOUNT: &str = "amount"; fn should_run_get_phase_contract() { let default_account = *DEFAULT_ACCOUNT_ADDR; - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_deploy_hash([1; 32]) - .with_session_code( - "get_phase.wasm", - runtime_args! { ARG_PHASE => Phase::Session }, - ) - .with_payment_code( - "get_phase_payment.wasm", - runtime_args! { - ARG_PHASE => Phase::Payment, - ARG_AMOUNT => *DEFAULT_PAYMENT - }, - ) - .with_authorization_keys(&[default_account]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_deploy_hash([1; 32]) + .with_session_code( + "get_phase.wasm", + runtime_args! { ARG_PHASE => Phase::Session }, + ) + .with_payment_code( + "get_phase_payment.wasm", + runtime_args! { + ARG_PHASE => Phase::Payment, + ARG_AMOUNT => *DEFAULT_PAYMENT + }, + ) + .with_authorization_keys(&[default_account]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .expect_success(); diff --git a/execution_engine_testing/tests/src/test/contract_api/list_authorization_keys.rs b/execution_engine_testing/tests/src/test/contract_api/list_authorization_keys.rs index d282c9b655..2341af92d1 100644 --- a/execution_engine_testing/tests/src/test/contract_api/list_authorization_keys.rs +++ b/execution_engine_testing/tests/src/test/contract_api/list_authorization_keys.rs @@ -1,14 +1,11 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ - account::AccountHash, - addressable_entity::Weight, - runtime_args, - system::{mint, standard_payment::ARG_AMOUNT}, - ApiError, PublicKey, SecretKey, U512, + account::AccountHash, addressable_entity::Weight, runtime_args, + system::standard_payment::ARG_AMOUNT, ApiError, PublicKey, SecretKey, }; use once_cell::sync::Lazy; @@ -42,7 +39,7 @@ fn should_list_authorization_keys() { test_match( *DEFAULT_ACCOUNT_ADDR, vec![*DEFAULT_ACCOUNT_ADDR], - vec![*DEFAULT_ACCOUNT_ADDR] + vec![*DEFAULT_ACCOUNT_ADDR], ), "one signature should match the expected authorization key" ); @@ -50,7 +47,7 @@ fn should_list_authorization_keys() { !test_match( *DEFAULT_ACCOUNT_ADDR, vec![*ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR], - vec![*DEFAULT_ACCOUNT_ADDR, *ACCOUNT_1_ADDR] + vec![*DEFAULT_ACCOUNT_ADDR, *ACCOUNT_1_ADDR], ), "two signatures are off by one" ); @@ -58,7 +55,7 @@ fn should_list_authorization_keys() { test_match( *DEFAULT_ACCOUNT_ADDR, vec![*ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR], - vec![*DEFAULT_ACCOUNT_ADDR, *ACCOUNT_2_ADDR] + vec![*DEFAULT_ACCOUNT_ADDR, *ACCOUNT_2_ADDR], ), "two signatures should match the expected list" ); @@ -66,7 +63,7 @@ fn should_list_authorization_keys() { test_match( *ACCOUNT_1_ADDR, vec![*ACCOUNT_1_ADDR], - vec![*ACCOUNT_1_ADDR] + vec![*ACCOUNT_1_ADDR], ), "one signature should match the output for non-default account" ); @@ -75,7 +72,7 @@ fn should_list_authorization_keys() { test_match( *DEFAULT_ACCOUNT_ADDR, vec![*ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR, *ACCOUNT_1_ADDR], - vec![*ACCOUNT_1_ADDR, *ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR] + vec![*ACCOUNT_1_ADDR, *ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR], ), "multisig matches expected list" ); @@ -83,7 +80,7 @@ fn should_list_authorization_keys() { !test_match( *DEFAULT_ACCOUNT_ADDR, vec![*ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR, *ACCOUNT_1_ADDR], - vec![] + vec![], ), "multisig is not empty" ); @@ -91,7 +88,7 @@ fn should_list_authorization_keys() { !test_match( *DEFAULT_ACCOUNT_ADDR, vec![*ACCOUNT_2_ADDR, *DEFAULT_ACCOUNT_ADDR, *ACCOUNT_1_ADDR], - vec![*ACCOUNT_2_ADDR, *ACCOUNT_1_ADDR] + vec![*ACCOUNT_2_ADDR, *ACCOUNT_1_ADDR], ), "multisig does not include caller account" ); @@ -103,23 +100,21 @@ fn test_match( expected_authorization_keys: Vec, ) -> bool { let mut builder = setup(); - let exec_request = { - let session_args = runtime_args! { - ARG_EXPECTED_AUTHORIZATION_KEYS => expected_authorization_keys - }; - let deploy_hash = [42; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(caller) - .with_session_code(CONTRACT_LIST_AUTHORIZATION_KEYS, session_args) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&signatures) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let session_args = runtime_args! { + ARG_EXPECTED_AUTHORIZATION_KEYS => expected_authorization_keys }; + let deploy_hash = [42; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(caller) + .with_session_code(CONTRACT_LIST_AUTHORIZATION_KEYS, session_args) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }) + .with_authorization_keys(&signatures) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit(); match builder.get_error() { @@ -134,7 +129,7 @@ fn test_match( fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for account in [*ACCOUNT_1_ADDR, *ACCOUNT_2_ADDR] { let add_key_request = { @@ -150,18 +145,13 @@ fn setup() -> LmdbWasmTestBuilder { .build() }; - let transfer_request = { - let transfer_args = runtime_args! { - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_TARGET => account, - mint::ARG_ID => Option::::None, - }; - - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build() - }; + let transfer_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, account).build(); builder.exec(add_key_request).expect_success().commit(); - builder.exec(transfer_request).expect_success().commit(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); } builder diff --git a/execution_engine_testing/tests/src/test/contract_api/list_named_keys.rs b/execution_engine_testing/tests/src/test/contract_api/list_named_keys.rs index 1e33837ec8..869d07b006 100644 --- a/execution_engine_testing/tests/src/test/contract_api/list_named_keys.rs +++ b/execution_engine_testing/tests/src/test/contract_api/list_named_keys.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, addressable_entity::NamedKeys, runtime_args, Key}; @@ -14,7 +13,7 @@ const ARG_NEW_NAMED_KEYS: &str = "new_named_keys"; #[test] fn should_list_named_keys() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let initial_named_keys: NamedKeys = NamedKeys::new(); diff --git a/execution_engine_testing/tests/src/test/contract_api/main_purse.rs b/execution_engine_testing/tests/src/test/contract_api/main_purse.rs index 5a1fd0049c..330ec9a014 100644 --- a/execution_engine_testing/tests/src/test/contract_api/main_purse.rs +++ b/execution_engine_testing/tests/src/test/contract_api/main_purse.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args}; @@ -15,7 +15,7 @@ const ARG_AMOUNT: &str = "amount"; fn should_run_main_purse_contract_default_account() { let mut builder = LmdbWasmTestBuilder::default(); - let builder = builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + let builder = builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -44,7 +44,7 @@ fn should_run_main_purse_contract_account_1() { .build(); let builder = builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/contract_api/mint_purse.rs b/execution_engine_testing/tests/src/test/contract_api/mint_purse.rs index 31d18cd74a..347246ceb1 100644 --- a/execution_engine_testing/tests/src/test/contract_api/mint_purse.rs +++ b/execution_engine_testing/tests/src/test/contract_api/mint_purse.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, SYSTEM_ADDR, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, }; use casper_types::{runtime_args, RuntimeArgs, U512}; @@ -23,7 +23,7 @@ fn should_run_mint_purse_contract() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).commit().expect_success(); builder.exec(exec_request_2).commit().expect_success(); @@ -40,7 +40,7 @@ fn should_not_allow_non_system_accounts_to_mint() { .build(); assert!(LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .is_error()); diff --git a/execution_engine_testing/tests/src/test/contract_api/mod.rs b/execution_engine_testing/tests/src/test/contract_api/mod.rs index a1a5354aea..1f2a6bb52c 100644 --- a/execution_engine_testing/tests/src/test/contract_api/mod.rs +++ b/execution_engine_testing/tests/src/test/contract_api/mod.rs @@ -1,4 +1,5 @@ mod account; +mod add_contract_version; mod create_purse; mod dictionary; mod get_arg; diff --git a/execution_engine_testing/tests/src/test/contract_api/multisig_authorization.rs b/execution_engine_testing/tests/src/test/contract_api/multisig_authorization.rs index 4419685c58..77375da334 100644 --- a/execution_engine_testing/tests/src/test/contract_api/multisig_authorization.rs +++ b/execution_engine_testing/tests/src/test/contract_api/multisig_authorization.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ @@ -146,21 +146,19 @@ fn test_multisig_auth( authorization_keys: &[AccountHash], ) -> bool { let mut builder = setup(); - let exec_request = { - let session_args = runtime_args! {}; - let payment_args = runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }; - let deploy_hash = [42; 32]; - let deploy = DeployItemBuilder::new() - .with_address(caller) - .with_stored_session_named_key(CONTRACT_KEY, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(authorization_keys) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let session_args = runtime_args! {}; + let payment_args = runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT }; + let deploy_hash = [42; 32]; + let deploy_item = DeployItemBuilder::new() + .with_address(caller) + .with_stored_session_named_key(CONTRACT_KEY, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(authorization_keys) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit(); match builder.get_error() { @@ -175,7 +173,7 @@ fn test_multisig_auth( fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for account in ROLE_A_KEYS.iter().chain(&ROLE_B_KEYS) { let add_key_request = { diff --git a/execution_engine_testing/tests/src/test/contract_api/named_dictionaries.rs b/execution_engine_testing/tests/src/test/contract_api/named_dictionaries.rs index ad6a7f056b..41764f61b0 100644 --- a/execution_engine_testing/tests/src/test/contract_api/named_dictionaries.rs +++ b/execution_engine_testing/tests/src/test/contract_api/named_dictionaries.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::runtime_args; use rand::{rngs::StdRng, Rng, SeedableRng}; @@ -20,7 +19,7 @@ fn named_dictionaries_should_work_as_expected() { .collect(); let builder = &mut LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec( ExecuteRequestBuilder::standard( diff --git a/execution_engine_testing/tests/src/test/contract_api/revert.rs b/execution_engine_testing/tests/src/test/contract_api/revert.rs index ea8b4e6aa5..56ab34bedb 100644 --- a/execution_engine_testing/tests/src/test/contract_api/revert.rs +++ b/execution_engine_testing/tests/src/test/contract_api/revert.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -13,7 +12,7 @@ fn should_revert() { ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, REVERT_WASM, RuntimeArgs::default()) .build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .is_error(); diff --git a/execution_engine_testing/tests/src/test/contract_api/runtime.rs b/execution_engine_testing/tests/src/test/contract_api/runtime.rs index 8939bcca39..6c093d731e 100644 --- a/execution_engine_testing/tests/src/test/contract_api/runtime.rs +++ b/execution_engine_testing/tests/src/test/contract_api/runtime.rs @@ -4,7 +4,7 @@ use rand::Rng; use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::runtime_context::RANDOM_BYTES_COUNT; use casper_storage::address_generator::ADDRESS_LENGTH; @@ -42,26 +42,24 @@ fn get_value(builder: &LmdbWasmTestBuilder, result: &str) -> #[test] fn should_return_different_random_bytes_on_different_phases() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let execute_request = { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - let address = *DEFAULT_ACCOUNT_ADDR; - let deploy = DeployItemBuilder::new() - .with_address(address) - .with_session_code(RANDOM_BYTES_WASM, runtime_args! {}) - .with_payment_code( - RANDOM_BYTES_PAYMENT_WASM, - runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }, - ) - .with_authorization_keys(&[address]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let mut rng = rand::thread_rng(); + let deploy_hash = rng.gen(); + let address = *DEFAULT_ACCOUNT_ADDR; + let deploy_item = DeployItemBuilder::new() + .with_address(address) + .with_session_code(RANDOM_BYTES_WASM, runtime_args! {}) + .with_payment_code( + RANDOM_BYTES_PAYMENT_WASM, + runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }, + ) + .with_authorization_keys(&[address]) + .with_deploy_hash(deploy_hash) + .build(); + let execute_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(execute_request).commit().expect_success(); @@ -79,7 +77,7 @@ fn should_return_different_random_bytes_on_each_call() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let all_addresses: HashSet<_> = (0..RUNS) .map(|_| { @@ -109,7 +107,7 @@ fn should_hash() { let mut rng = rand::thread_rng(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for _ in 0..RUNS { let input: [u8; INPUT_LENGTH] = rng.gen(); diff --git a/execution_engine_testing/tests/src/test/contract_api/subcall.rs b/execution_engine_testing/tests/src/test/contract_api/subcall.rs index 2cca9dedf5..a50c9ad6c1 100644 --- a/execution_engine_testing/tests/src/test/contract_api/subcall.rs +++ b/execution_engine_testing/tests/src/test/contract_api/subcall.rs @@ -1,12 +1,9 @@ use num_traits::cast::AsPrimitive; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_types::{ - package::ENTITY_INITIAL_VERSION, runtime_args, RuntimeArgs, StorageCosts, U512, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; +use casper_types::{runtime_args, RuntimeArgs, StorageCosts, ENTITY_INITIAL_VERSION, U512}; const ARG_TARGET: &str = "target_contract"; const ARG_GAS_AMOUNT: &str = "gas_amount"; @@ -43,7 +40,7 @@ fn should_charge_gas_for_subcall() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(do_nothing_request).expect_success().commit(); @@ -51,11 +48,11 @@ fn should_charge_gas_for_subcall() { builder.exec(no_subcall_request).expect_success().commit(); - let do_nothing_cost = builder.exec_costs(0)[0]; + let do_nothing_cost = builder.exec_cost(0); - let do_something_cost = builder.exec_costs(1)[0]; + let do_something_cost = builder.exec_cost(1); - let no_subcall_cost = builder.exec_costs(2)[0]; + let no_subcall_cost = builder.exec_cost(2); assert_ne!( do_nothing_cost, do_something_cost, @@ -131,7 +128,7 @@ fn should_add_all_gas_for_subcall() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(add_zero_gas_from_session_request) @@ -150,10 +147,10 @@ fn should_add_all_gas_for_subcall() { .expect_success() .commit(); - let add_zero_gas_from_session_cost = builder.exec_costs(0)[0]; - let add_some_gas_from_session_cost = builder.exec_costs(1)[0]; - let add_zero_gas_via_subcall_cost = builder.exec_costs(2)[0]; - let add_some_gas_via_subcall_cost = builder.exec_costs(3)[0]; + let add_zero_gas_from_session_cost = builder.exec_cost(0); + let add_some_gas_from_session_cost = builder.exec_cost(1); + let add_zero_gas_via_subcall_cost = builder.exec_cost(2); + let add_some_gas_via_subcall_cost = builder.exec_cost(3); let expected_gas = U512::from(StorageCosts::default().gas_per_byte()) * gas_to_add; assert!( @@ -187,7 +184,7 @@ fn expensive_subcall_should_cost_more() { let mut builder = LmdbWasmTestBuilder::default(); // store the contracts first - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(store_do_nothing_request) @@ -239,9 +236,9 @@ fn expensive_subcall_should_cost_more() { .expect_success() .commit(); - let do_nothing_cost = builder.exec_costs(2)[0]; + let do_nothing_cost = builder.exec_cost(2); - let expensive_calculation_cost = builder.exec_costs(3)[0]; + let expensive_calculation_cost = builder.exec_cost(3); assert!( do_nothing_cost < expensive_calculation_cost, diff --git a/execution_engine_testing/tests/src/test/contract_api/transfer.rs b/execution_engine_testing/tests/src/test/contract_api/transfer.rs index e1502d274a..60a378ce43 100644 --- a/execution_engine_testing/tests/src/test/contract_api/transfer.rs +++ b/execution_engine_testing/tests/src/test/contract_api/transfer.rs @@ -3,8 +3,8 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state::Error as EngineError, execution::ExecError}; use casper_types::{ @@ -54,7 +54,7 @@ fn should_transfer_to_account() { // Run genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -107,7 +107,7 @@ fn should_transfer_to_public_key() { // Run genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -158,7 +158,7 @@ fn should_transfer_from_purse_to_public_key() { // Run genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Create a funded a purse, and store it in named keys let exec_request_1 = ExecuteRequestBuilder::standard( @@ -240,7 +240,7 @@ fn should_transfer_from_account_to_account() { // Run genesis let mut builder = LmdbWasmTestBuilder::default(); - let builder = builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + let builder = builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -330,7 +330,7 @@ fn should_transfer_to_existing_account() { // Run genesis let mut builder = LmdbWasmTestBuilder::default(); - let builder = builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + let builder = builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -447,7 +447,7 @@ fn should_fail_when_insufficient_funds() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) // Exec transfer contract .exec(exec_request_1) .expect_success() @@ -460,51 +460,115 @@ fn should_fail_when_insufficient_funds() { .exec(exec_request_3) .commit(); - let exec_results = builder + let exec_result = builder .get_exec_result_owned(2) .expect("should have exec response"); - assert_eq!(exec_results.len(), 1); - let exec_result = exec_results[0].as_error().expect("should have error"); - let error = assert_matches!(exec_result, EngineError::Exec(ExecError::Revert(e)) => *e, "{:?}", exec_result); - assert_eq!(error, ApiError::from(mint::Error::InsufficientFunds)); + let exec_result = exec_result.error().expect("should have error"); + let error = assert_matches!(exec_result, EngineError::Exec(ExecError::Revert(e)) => e, "{:?}", exec_result); + assert_eq!(*error, ApiError::from(mint::Error::InsufficientFunds)); } #[ignore] +#[allow(unused)] #[test] fn should_transfer_total_amount() { - let mut builder = LmdbWasmTestBuilder::default(); - - let exec_request_1 = ExecuteRequestBuilder::standard( - *DEFAULT_ACCOUNT_ADDR, - CONTRACT_TRANSFER_PURSE_TO_ACCOUNT, - runtime_args! { "target" => *ACCOUNT_1_ADDR, "amount" => *ACCOUNT_1_INITIAL_BALANCE }, - ) - .build(); - - let transfer_amount_1 = *ACCOUNT_1_INITIAL_BALANCE - *DEFAULT_PAYMENT; - - let exec_request_2 = ExecuteRequestBuilder::standard( - *ACCOUNT_1_ADDR, - CONTRACT_TRANSFER_PURSE_TO_ACCOUNT, - runtime_args! { "target" => *ACCOUNT_2_ADDR, "amount" => transfer_amount_1 }, - ) - .build(); - - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - builder.exec(exec_request_1).expect_success().commit(); - - builder.exec(exec_request_2).commit().expect_success(); + // NOTE: as of protocol version 2.0.0 the execution engine is no longer reponsible + // for payment, refund, or fee handling...thus + // full transactions executed via the node are subject to payment, fee, refund, + // etc based upon chainspec settings, but when using the EE directly as is done + // in this test, there is no charge and all transfers are at face value. + fn balance_checker(bldr: &mut LmdbWasmTestBuilder, account_hash: AccountHash) -> U512 { + let entity = bldr + .get_entity_by_account_hash(account_hash) + .expect("should have account entity"); + let entity_main_purse = entity.main_purse(); + bldr.get_purse_balance(entity_main_purse) + } + fn commit(bldr: &mut LmdbWasmTestBuilder, req_bldr: ExecuteRequestBuilder) { + let req = req_bldr.build(); + bldr.exec(req).expect_success().commit(); + } + fn genesis() -> LmdbWasmTestBuilder { + let mut builder = LmdbWasmTestBuilder::default(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + builder + } + + let mut builder = genesis(); + + let balance_x_initial = balance_checker(&mut builder, *DEFAULT_ACCOUNT_ADDR); + let amount_to_fund = *ACCOUNT_1_INITIAL_BALANCE; + + // fund account 1 from default account + commit( + &mut builder, + ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_TRANSFER_PURSE_TO_ACCOUNT, + runtime_args! { "target" => *ACCOUNT_1_ADDR, "amount" => amount_to_fund }, + ), + ); + let balance_x_out = balance_checker(&mut builder, *DEFAULT_ACCOUNT_ADDR); + assert_eq!( + balance_x_initial - amount_to_fund, + balance_x_out, + "funded amount should be deducted from funder's balance" + ); + let balance_y_initial = balance_checker(&mut builder, *ACCOUNT_1_ADDR); + assert_eq!( + amount_to_fund, balance_y_initial, + "receiving account's balance should match funding amount" + ); + let diff = balance_x_initial - balance_y_initial; + assert_eq!( + diff, balance_x_out, + "funder's balance difference should equal funded amount" + ); - let account_1 = builder - .get_entity_by_account_hash(*ACCOUNT_1_ADDR) - .expect("should have account"); - let account_1_main_purse = account_1.main_purse(); - let account_1_balance = builder.get_purse_balance(account_1_main_purse); + // transfer it to a different account + commit( + &mut builder, + ExecuteRequestBuilder::standard( + *ACCOUNT_1_ADDR, + CONTRACT_TRANSFER_PURSE_TO_ACCOUNT, + runtime_args! { "target" => *ACCOUNT_2_ADDR, "amount" => balance_y_initial }, + ), + ); + let balance_y_out = balance_checker(&mut builder, *ACCOUNT_1_ADDR); + assert_eq!( + balance_y_initial - amount_to_fund, + balance_y_out, + "funded amount should be deducted from funder's balance" + ); + let balance_z_initial = balance_checker(&mut builder, *ACCOUNT_2_ADDR); + assert_eq!( + amount_to_fund, balance_z_initial, + "receiving account's balance should match funding amount" + ); + let diff = balance_y_initial - balance_z_initial; + assert_eq!( + diff, balance_y_out, + "funder's balance difference should equal funded amount" + ); + // transfer it back to originator + commit( + &mut builder, + ExecuteRequestBuilder::standard( + *ACCOUNT_2_ADDR, + CONTRACT_TRANSFER_PURSE_TO_ACCOUNT, + runtime_args! { "target" => *DEFAULT_ACCOUNT_ADDR, "amount" => balance_z_initial }, + ), + ); + let balance_x_in = balance_checker(&mut builder, *DEFAULT_ACCOUNT_ADDR); + let balance_z_out = balance_checker(&mut builder, *ACCOUNT_2_ADDR); assert_eq!( - account_1_balance, - builder.calculate_refund_amount(*DEFAULT_PAYMENT), - "account 1 should only have refunded amount after transferring full amount" + U512::zero(), + balance_z_out, + "trampoline account should be zero'd" + ); + assert_eq!( + balance_x_initial, balance_x_in, + "original balance should be restored" ); } diff --git a/execution_engine_testing/tests/src/test/contract_api/transfer_cached.rs b/execution_engine_testing/tests/src/test/contract_api/transfer_cached.rs index 88457c6ae4..3c920b3c75 100644 --- a/execution_engine_testing/tests/src/test/contract_api/transfer_cached.rs +++ b/execution_engine_testing/tests/src/test/contract_api/transfer_cached.rs @@ -1,18 +1,12 @@ use once_cell::sync::Lazy; -use rand::Rng; use tempfile::TempDir; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_INITIAL_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_execution_engine::engine_state::{DeployItem, MAX_PAYMENT_AMOUNT}; -use casper_types::{ - account::AccountHash, - runtime_args, - system::mint::{ARG_AMOUNT, ARG_ID, ARG_TARGET}, - MintCosts, PublicKey, RuntimeArgs, SecretKey, U512, + LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + DEFAULT_ACCOUNT_INITIAL_BALANCE, LOCAL_GENESIS_REQUEST, }; +use casper_execution_engine::engine_state::MAX_PAYMENT_AMOUNT; +use casper_types::{account::AccountHash, MintCosts, PublicKey, SecretKey, U512}; static TRANSFER_AMOUNT: Lazy = Lazy::new(|| U512::from(MAX_PAYMENT_AMOUNT)); @@ -28,35 +22,22 @@ static ACCOUNT_2_PUBLIC_KEY: Lazy = Lazy::new(|| PublicKey::from(&*ACCOUNT_2_SECRET_KEY)); static ACCOUNT_2_ADDR: Lazy = Lazy::new(|| ACCOUNT_2_PUBLIC_KEY.to_account_hash()); -const ID_NONE: Option = None; - #[ignore] #[test] fn should_transfer_to_account_with_correct_balances() { let data_dir = TempDir::new().expect("should create temp dir"); let mut builder = LmdbWasmTestBuilder::new(data_dir.path()); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let pre_state_hash = builder.get_post_state_hash(); // Default account to account 1 - let mut exec_builder = ExecuteRequestBuilder::new(); - exec_builder = exec_builder.push_deploy(transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => *ACCOUNT_1_ADDR, - ARG_AMOUNT => U512::one(), - ARG_ID => ID_NONE, - }, - )); + let transfer_request = TransferRequestBuilder::new(1, *ACCOUNT_1_ADDR).build(); builder - .scratch_exec_and_commit(exec_builder.build()) + .transfer_and_commit(transfer_request) .expect_success(); - builder.write_scratch_to_db(); - builder.flush_environment(); - assert_ne!( pre_state_hash, builder.get_post_state_hash(), @@ -93,58 +74,37 @@ fn should_transfer_from_default_and_then_to_another_account() { let data_dir = TempDir::new().expect("should create temp dir"); let mut builder = LmdbWasmTestBuilder::new(data_dir.path()); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let pre_state_hash = builder.get_post_state_hash(); // Default account to account 1 - let mut exec_builder = ExecuteRequestBuilder::new(); // We must first transfer the amount account 1 will transfer to account 2, along with the fee // account 1 will need to pay for that transfer. - exec_builder = exec_builder.push_deploy(transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - ARG_TARGET => *ACCOUNT_1_ADDR, - ARG_AMOUNT => *TRANSFER_AMOUNT + MintCosts::default().transfer, - ARG_ID => ID_NONE, - }, - )); + let transfer_request = TransferRequestBuilder::new( + *TRANSFER_AMOUNT + MintCosts::default().transfer, + *ACCOUNT_1_ADDR, + ) + .build(); builder - .scratch_exec_and_commit(exec_builder.build()) + .transfer_and_commit(transfer_request) .expect_success(); - let mut exec_builder = ExecuteRequestBuilder::new(); - exec_builder = exec_builder.push_deploy(transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - ARG_TARGET => *ACCOUNT_2_ADDR, - ARG_AMOUNT => *TRANSFER_AMOUNT, - ARG_ID => ID_NONE, - }, - )); - + let transfer_request = TransferRequestBuilder::new(*TRANSFER_AMOUNT, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); builder - .scratch_exec_and_commit(exec_builder.build()) + .transfer_and_commit(transfer_request) .expect_success(); // Double spend test for account 1 - let mut exec_builder = ExecuteRequestBuilder::new(); - exec_builder = exec_builder.push_deploy(transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - ARG_TARGET => *ACCOUNT_2_ADDR, - ARG_AMOUNT => *TRANSFER_AMOUNT, - ARG_ID => ID_NONE, - }, - )); - + let transfer_request = TransferRequestBuilder::new(*TRANSFER_AMOUNT, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); builder - .scratch_exec_and_commit(exec_builder.build()) + .transfer_and_commit(transfer_request) .expect_failure(); - builder.write_scratch_to_db(); - builder.flush_environment(); - assert_ne!( pre_state_hash, builder.get_post_state_hash(), @@ -187,15 +147,3 @@ fn should_transfer_from_default_and_then_to_another_account() { "account 2 balance should have changed" ); } - -fn transfer(sender: AccountHash, transfer_args: RuntimeArgs) -> DeployItem { - let mut rng = rand::thread_rng(); - let deploy_hash = rng.gen(); - DeployItemBuilder::new() - .with_address(sender) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(transfer_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build() -} diff --git a/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_account.rs b/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_account.rs index 6d414e22a6..b41b0b72bf 100644 --- a/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_account.rs +++ b/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_account.rs @@ -3,7 +3,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{ account::AccountHash, @@ -24,7 +24,7 @@ static ACCOUNT_1_INITIAL_FUND: Lazy = Lazy::new(|| *DEFAULT_PAYMENT + 42); #[test] fn should_run_purse_to_account_transfer() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let account_1_account_hash = ACCOUNT_1_ADDR; assert!( @@ -56,7 +56,8 @@ fn should_run_purse_to_account_transfer() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_fail_when_sending_too_much_from_purse_to_account() { let account_1_key = ACCOUNT_1_ADDR; @@ -69,7 +70,7 @@ fn should_fail_when_sending_too_much_from_purse_to_account() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_failure().commit(); diff --git a/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_purse.rs b/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_purse.rs index ceb613ad05..3a686e321a 100644 --- a/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_purse.rs +++ b/execution_engine_testing/tests/src/test/contract_api/transfer_purse_to_purse.rs @@ -4,7 +4,7 @@ use casper_types::{runtime_args, system::mint, ApiError, CLValue, U512}; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; const CONTRACT_TRANSFER_PURSE_TO_PURSE: &str = "transfer_purse_to_purse.wasm"; @@ -14,7 +14,8 @@ const ARG_TARGET: &str = "target"; const ARG_AMOUNT: &str = "amount"; #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_purse_to_purse_transfer() { let source = "purse:main".to_string(); let target = "purse:secondary".to_string(); @@ -32,7 +33,7 @@ fn should_run_purse_to_purse_transfer() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit(); @@ -89,7 +90,8 @@ fn should_run_purse_to_purse_transfer() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_purse_to_purse_transfer_with_error() { // This test runs a contract that's after every call extends the same key with // more data @@ -103,7 +105,7 @@ fn should_run_purse_to_purse_transfer_with_error() { .build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/contract_context.rs b/execution_engine_testing/tests/src/test/contract_context.rs index 850cd237aa..d39974d1ff 100644 --- a/execution_engine_testing/tests/src/test/contract_context.rs +++ b/execution_engine_testing/tests/src/test/contract_context.rs @@ -1,9 +1,8 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; -use casper_types::{package::ENTITY_INITIAL_VERSION, runtime_args, Key, RuntimeArgs}; +use casper_types::{runtime_args, Key, RuntimeArgs, ENTITY_INITIAL_VERSION}; const CONTRACT_HEADERS: &str = "contract_context.wasm"; const PACKAGE_HASH_KEY: &str = "package_hash_key"; @@ -38,7 +37,7 @@ fn should_enforce_intended_execution_contexts() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -95,7 +94,7 @@ fn should_enforce_intended_execution_context_direct_by_name() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -130,7 +129,7 @@ fn should_enforce_intended_execution_context_direct_by_hash() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/contract_messages.rs b/execution_engine_testing/tests/src/test/contract_messages.rs index 9d26dbe1e9..36d99c017e 100644 --- a/execution_engine_testing/tests/src/test/contract_messages.rs +++ b/execution_engine_testing/tests/src/test/contract_messages.rs @@ -3,9 +3,8 @@ use std::cell::RefCell; use casper_engine_test_support::{ ChainspecConfig, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_BLOCK_TIME, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_BLOCK_TIME, LOCAL_GENESIS_REQUEST, }; -use casper_execution_engine::engine_state::ExecutionResult; use casper_types::{ bytesrepr::ToBytes, contract_messages::{MessageChecksum, MessagePayload, MessageTopicSummary, TopicNameHash}, @@ -201,7 +200,7 @@ impl<'a> ContractQueryView<'a> { .query( None, Key::message_topic( - EntityAddr::new_contract_entity_addr(self.contract_hash.value()), + EntityAddr::new_smart_contract(self.contract_hash.value()), topic_name_hash, ), &[], @@ -228,7 +227,7 @@ impl<'a> ContractQueryView<'a> { let query_result = self.builder.borrow_mut().query( state_hash, Key::message( - EntityAddr::new_contract_entity_addr(self.contract_hash.value()), + EntityAddr::new_smart_contract(self.contract_hash.value()), topic_name_hash, message_index, ), @@ -248,7 +247,7 @@ fn should_emit_messages() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -359,7 +358,7 @@ fn should_emit_message_on_empty_topic_in_new_block() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -398,7 +397,7 @@ fn should_add_topics() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -462,7 +461,7 @@ fn should_not_add_duplicate_topics() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -516,7 +515,7 @@ fn should_not_exceed_configured_limits() { let builder = RefCell::new(LmdbWasmTestBuilder::new_temporary_with_config(chainspec)); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); @@ -600,7 +599,7 @@ fn should_carry_message_topics_on_upgraded_contract(use_initializer: bool) { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let _ = install_messages_emitter_contract(&builder, true); let contract_hash = upgrade_messages_emitter_contract(&builder, use_initializer, false); @@ -639,7 +638,7 @@ fn should_not_emit_messages_from_account() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Request to run a deploy that tries to register a message topic without a stored contract. let install_request = ExecuteRequestBuilder::standard( @@ -678,7 +677,7 @@ fn should_charge_expected_gas_for_storage() { let builder = RefCell::new(LmdbWasmTestBuilder::new_temporary_with_config(chainspec)); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -783,7 +782,7 @@ fn should_charge_increasing_gas_cost_for_multiple_messages_emitted() { let builder = RefCell::new(LmdbWasmTestBuilder::new_temporary_with_config(chainspec)); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, true); @@ -853,7 +852,7 @@ fn should_register_topic_on_contract_creation() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let contract_hash = install_messages_emitter_contract(&builder, false); let query_view = ContractQueryView::new(&builder, contract_hash); @@ -900,7 +899,7 @@ fn should_not_exceed_configured_topic_name_limits_on_contract_upgrade_no_init() let builder = RefCell::new(LmdbWasmTestBuilder::new_temporary_with_config(chainspec)); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let _ = install_messages_emitter_contract(&builder, false); let _ = upgrade_messages_emitter_contract(&builder, false, true); @@ -932,7 +931,7 @@ fn should_not_exceed_configured_max_topics_per_contract_upgrade_no_init() { let builder = RefCell::new(LmdbWasmTestBuilder::new_temporary_with_config(chainspec)); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let _ = install_messages_emitter_contract(&builder, false); let _ = upgrade_messages_emitter_contract(&builder, false, true); @@ -944,7 +943,7 @@ fn should_produce_per_block_message_ordering() { let builder = RefCell::new(LmdbWasmTestBuilder::default()); builder .borrow_mut() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + .run_genesis(LOCAL_GENESIS_REQUEST.clone()); let emitter_contract_hash = install_messages_emitter_contract(&builder, true); let query_view = ContractQueryView::new(&builder, emitter_contract_hash); @@ -957,20 +956,17 @@ fn should_produce_per_block_message_ordering() { .expect("should have at least one topic"); let assert_last_message_block_index = |expected_index: u64| { - match &**builder - .borrow() - .get_last_exec_result() - .unwrap() - .get(0) - .unwrap() - { - ExecutionResult::Failure { .. } => { - panic!("Expected that the message was emitted but the request did not produce successful execution effects"); - } - ExecutionResult::Success { messages, .. } => { - assert_eq!(messages.get(0).unwrap().block_index(), expected_index); - } - }; + assert_eq!( + builder + .borrow() + .get_last_exec_result() + .unwrap() + .messages() + .get(0) + .unwrap() + .block_index(), + expected_index + ) }; let query_message_count = || -> Option<(BlockTime, u64)> { diff --git a/execution_engine_testing/tests/src/test/counter_factory.rs b/execution_engine_testing/tests/src/test/counter_factory.rs index 5c54279498..b9af4aae07 100644 --- a/execution_engine_testing/tests/src/test/counter_factory.rs +++ b/execution_engine_testing/tests/src/test/counter_factory.rs @@ -2,8 +2,7 @@ use std::{collections::BTreeSet, iter::FromIterator}; use crate::wasm_utils; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ @@ -222,7 +221,7 @@ fn should_install_and_use_factory_pattern() { fn setup() -> (LmdbWasmTestBuilder, AddressableEntityHash) { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/deploy/context_association.rs b/execution_engine_testing/tests/src/test/deploy/context_association.rs index 7f8f60632c..109e2986d0 100644 --- a/execution_engine_testing/tests/src/test/deploy/context_association.rs +++ b/execution_engine_testing/tests/src/test/deploy/context_association.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_KEY, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_KEY, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{ @@ -17,20 +17,18 @@ fn should_put_system_contract_hashes_to_account_context() { let payment_purse_amount = *DEFAULT_PAYMENT; let mut builder = LmdbWasmTestBuilder::default(); - let request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code(SYSTEM_CONTRACT_HASHES_WASM, runtime_args! {}) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount}) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([1; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code(SYSTEM_CONTRACT_HASHES_WASM, runtime_args! {}) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount}) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([1; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/deploy/non_standard_payment.rs b/execution_engine_testing/tests/src/test/deploy/non_standard_payment.rs index 7adcd310aa..cac1baa96c 100644 --- a/execution_engine_testing/tests/src/test/deploy/non_standard_payment.rs +++ b/execution_engine_testing/tests/src/test/deploy/non_standard_payment.rs @@ -1,8 +1,11 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; -use casper_types::{account::AccountHash, runtime_args, RuntimeArgs, U512}; +use casper_execution_engine::engine_state::WasmV1Request; +use casper_storage::data_access_layer::BalanceIdentifier; +use casper_types::{account::AccountHash, runtime_args, Digest, Gas, RuntimeArgs, Timestamp, U512}; const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([42u8; 32]); const DO_NOTHING_WASM: &str = "do_nothing.wasm"; @@ -15,6 +18,7 @@ const ARG_PURSE_NAME: &str = "purse_name"; const ARG_DESTINATION: &str = "destination"; #[ignore] +#[allow(unused)] #[test] fn should_charge_non_main_purse() { // as account_1, create & fund a new purse and use that to pay for something @@ -22,7 +26,6 @@ fn should_charge_non_main_purse() { const TEST_PURSE_NAME: &str = "test-purse"; let account_1_account_hash = ACCOUNT_1_ADDR; - let payment_purse_amount = *DEFAULT_PAYMENT; let account_1_funding_amount = U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE); let account_1_purse_funding_amount = *DEFAULT_PAYMENT; @@ -40,9 +43,9 @@ fn should_charge_non_main_purse() { TRANSFER_MAIN_PURSE_TO_NEW_PURSE_WASM, runtime_args! { ARG_DESTINATION => TEST_PURSE_NAME, ARG_AMOUNT => account_1_purse_funding_amount }, ) - .build(); + .build(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(setup_exec_request) @@ -59,48 +62,71 @@ fn should_charge_non_main_purse() { // get purse let purse_key = account_1.named_keys().get(TEST_PURSE_NAME).unwrap(); let purse = purse_key.into_uref().expect("should have uref"); - let purse_starting_balance = builder.get_purse_balance(purse); assert_eq!( purse_starting_balance, account_1_purse_funding_amount, - "purse should be funded with expected amount" + "purse should be funded with expected amount, which in this case is also == to the amount to be paid" ); + // in this test, we're just going to pay everything in the purse to + // keep the math easy. + let amount_to_be_paid = account_1_purse_funding_amount; // should be able to pay for exec using new purse - let account_payment_exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) - .with_payment_code( - NAMED_PURSE_PAYMENT_WASM, - runtime_args! { - ARG_PURSE_NAME => TEST_PURSE_NAME, - ARG_AMOUNT => payment_purse_amount - }, - ) - .with_authorization_keys(&[account_1_account_hash]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) + .with_payment_code( + NAMED_PURSE_PAYMENT_WASM, + runtime_args! { + ARG_PURSE_NAME => TEST_PURSE_NAME, + ARG_AMOUNT => amount_to_be_paid + }, + ) + .with_authorization_keys(&[account_1_account_hash]) + .with_deploy_hash([3; 32]) + .build(); + + let block_time = Timestamp::now().millis(); builder - .exec(account_payment_exec_request) + .exec_wasm_v1( + WasmV1Request::new_custom_payment_from_deploy_item( + Digest::default(), + block_time.into(), + Gas::from(12_500_000_000_u64), + &deploy_item, + ) + .expect("should be valid req"), + ) .expect_success() .commit(); - let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; + let payment_purse_balance = builder.get_purse_balance_result( + DEFAULT_PROTOCOL_VERSION, + BalanceIdentifier::Payment, + block_time, + ); + + assert!( + payment_purse_balance.is_success(), + "payment purse balance check should succeed" + ); - let expected_resting_balance = account_1_purse_funding_amount - transaction_fee; + let paid_amount = *payment_purse_balance + .motes() + .expect("should have payment amount"); + + assert_eq!( + paid_amount, amount_to_be_paid, + "purse resting balance should equal funding amount minus exec costs" + ); let purse_final_balance = builder.get_purse_balance(purse); assert_eq!( - purse_final_balance, expected_resting_balance, - "purse resting balance should equal funding amount minus exec costs" + purse_final_balance, + U512::zero(), + "since we zero'd out the paying purse, the final balance should be zero" ); } diff --git a/execution_engine_testing/tests/src/test/deploy/preconditions.rs b/execution_engine_testing/tests/src/test/deploy/preconditions.rs index 16a56f7d9d..c26274f1db 100644 --- a/execution_engine_testing/tests/src/test/deploy/preconditions.rs +++ b/execution_engine_testing/tests/src/test/deploy/preconditions.rs @@ -2,7 +2,7 @@ use assert_matches::assert_matches; use casper_engine_test_support::{ utils, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::Error; use casper_storage::tracking_copy::TrackingCopyError; @@ -19,8 +19,7 @@ fn should_raise_precondition_authorization_failure_invalid_account() { let payment_purse_amount = 10_000_000; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) .with_session_code( @@ -28,16 +27,15 @@ fn should_raise_precondition_authorization_failure_invalid_account() { runtime_args! { "target" =>account_1_account_hash, "amount" => U512::from(transferred_amount) }, ) // .with_address(nonexistent_account_addr) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => U512::from(payment_purse_amount) }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => U512::from(payment_purse_amount) }) .with_authorization_keys(&[nonexistent_account_addr]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); @@ -56,22 +54,20 @@ fn should_raise_precondition_authorization_failure_invalid_account() { #[test] fn should_raise_precondition_authorization_failure_empty_authorized_keys() { let empty_keys: [AccountHash; 0] = []; - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code("do_nothing.wasm", RuntimeArgs::default()) - .with_empty_payment_bytes(RuntimeArgs::default()) - .with_deploy_hash([1; 32]) - // empty authorization keys to force error - .with_authorization_keys(&empty_keys) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code("do_nothing.wasm", RuntimeArgs::default()) + .with_standard_payment(RuntimeArgs::default()) + .with_deploy_hash([1; 32]) + // empty authorization keys to force error + .with_authorization_keys(&empty_keys) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); @@ -94,25 +90,23 @@ fn should_raise_precondition_authorization_failure_invalid_authorized_keys() { let payment_purse_amount = 10_000_000; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) .with_session_code( "transfer_purse_to_account.wasm", runtime_args! { "target" =>account_1_account_hash, "amount" => U512::from(transferred_amount) }, ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => U512::from(payment_purse_amount) }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => U512::from(payment_purse_amount) }) // invalid authorization key to force error .with_authorization_keys(&[nonexistent_account_addr]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); diff --git a/execution_engine_testing/tests/src/test/deploy/receipts.rs b/execution_engine_testing/tests/src/test/deploy/receipts.rs index 1374e20caf..1496e4215e 100644 --- a/execution_engine_testing/tests/src/test/deploy/receipts.rs +++ b/execution_engine_testing/tests/src/test/deploy/receipts.rs @@ -3,12 +3,12 @@ use std::collections::{BTreeMap, BTreeSet}; use once_cell::sync::Lazy; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + LOCAL_GENESIS_REQUEST, }; use casper_types::{ - account::AccountHash, runtime_args, system::mint, AccessRights, DeployHash, PublicKey, - SecretKey, Transfer, TransferAddr, U512, + account::AccountHash, runtime_args, system::mint, AccessRights, Gas, InitiatorAddr, PublicKey, + SecretKey, Transfer, TransferV2, U512, }; const CONTRACT_TRANSFER_PURSE_TO_ACCOUNT: &str = "transfer_purse_to_account.wasm"; @@ -51,30 +51,19 @@ static TRANSFER_AMOUNT_3: Lazy = Lazy::new(|| U512::from(300_100_000)); #[test] fn should_record_wasmless_transfer() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let id = Some(0); + let id = 0; - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - TRANSFER_ARG_TARGET => *ALICE_ADDR, - TRANSFER_ARG_AMOUNT => *TRANSFER_AMOUNT_1, - TRANSFER_ARG_ID => id - }, - ) - .build(); + let transfer_request = TransferRequestBuilder::new(*TRANSFER_AMOUNT_1, *ALICE_ADDR) + .with_transfer_id(id) + .build(); - let deploy_hash = { - let deploy_items: Vec = transfer_request - .deploys() - .iter() - .map(|deploy_item| deploy_item.deploy_hash) - .collect(); - deploy_items[0] - }; + let txn_hash = transfer_request.transaction_hash(); - builder.exec(transfer_request).commit().expect_success(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -88,39 +77,35 @@ fn should_record_wasmless_transfer() { .main_purse() .with_access_rights(AccessRights::ADD); - let deploy_info = builder - .get_deploy_info(deploy_hash) - .expect("should have deploy info"); - - assert_eq!(deploy_info.deploy_hash, deploy_hash); - assert_eq!(deploy_info.from, *DEFAULT_ACCOUNT_ADDR); - assert_eq!(deploy_info.source, default_account.main_purse()); - - // TODO: reenable after new payment logic is added - // assert_eq!(deploy_info.gas, U512::from(DEFAULT_WASMLESS_TRANSFER_COST)); + let execution_result = builder + .get_last_exec_result() + .expect("Expected execution results."); - let transfers = deploy_info.transfers; + let transfers = execution_result.transfers(); assert_eq!(transfers.len(), 1); - let transfer = builder - .get_transfer(transfers[0]) - .expect("should have transfer"); + let Transfer::V2(transfer) = transfers[0].clone() else { + panic!("wrong transfer variant"); + }; - assert_eq!(transfer.deploy_hash, deploy_hash); - assert_eq!(transfer.from, *DEFAULT_ACCOUNT_ADDR); + assert_eq!(transfer.transaction_hash, txn_hash); + assert_eq!( + transfer.from, + InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR) + ); assert_eq!(transfer.to, Some(*ALICE_ADDR)); assert_eq!(transfer.source, default_account.main_purse()); assert_eq!(transfer.target, alice_attenuated_main_purse); assert_eq!(transfer.amount, *TRANSFER_AMOUNT_1); - assert_eq!(transfer.gas, U512::zero()); - assert_eq!(transfer.id, id); + assert_eq!(transfer.gas, Gas::zero()); + assert_eq!(transfer.id, Some(id)); } #[ignore] #[test] fn should_record_wasm_transfer() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -132,14 +117,7 @@ fn should_record_wasm_transfer() { ) .build(); - let deploy_hash = { - let deploy_items: Vec = transfer_request - .deploys() - .iter() - .map(|deploy_item| deploy_item.deploy_hash) - .collect(); - deploy_items[0] - }; + let txn_hash = transfer_request.session.transaction_hash; builder.exec(transfer_request).commit().expect_success(); @@ -155,35 +133,34 @@ fn should_record_wasm_transfer() { .main_purse() .with_access_rights(AccessRights::ADD); - let deploy_info = builder - .get_deploy_info(deploy_hash) - .expect("should have deploy info"); + let execution_result = builder + .get_last_exec_result() + .expect("Expected execution results."); - assert_eq!(deploy_info.deploy_hash, deploy_hash); - assert_eq!(deploy_info.from, *DEFAULT_ACCOUNT_ADDR); - assert_eq!(deploy_info.source, default_account.main_purse()); - assert_ne!(deploy_info.gas, U512::zero()); - - let transfers = deploy_info.transfers; + assert_ne!(execution_result.consumed(), Gas::zero()); + let transfers = execution_result.transfers(); assert_eq!(transfers.len(), 1); - let transfer = builder - .get_transfer(transfers[0]) - .expect("should have transfer"); + let Transfer::V2(transfer) = transfers[0].clone() else { + panic!("wrong transfer variant"); + }; - assert_eq!(transfer.deploy_hash, deploy_hash); - assert_eq!(transfer.from, *DEFAULT_ACCOUNT_ADDR); + assert_eq!(transfer.transaction_hash, txn_hash); + assert_eq!( + transfer.from, + InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR) + ); assert_eq!(transfer.source, default_account.main_purse()); assert_eq!(transfer.target, alice_attenuated_main_purse); assert_eq!(transfer.amount, *TRANSFER_AMOUNT_1); - assert_eq!(transfer.gas, U512::zero()) // TODO + assert_eq!(transfer.gas, Gas::zero()) // TODO } #[ignore] #[test] fn should_record_wasm_transfer_with_id() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let id = Some(0); @@ -198,14 +175,7 @@ fn should_record_wasm_transfer_with_id() { ) .build(); - let deploy_hash = { - let deploy_items: Vec = transfer_request - .deploys() - .iter() - .map(|deploy_item| deploy_item.deploy_hash) - .collect(); - deploy_items[0] - }; + let txn_hash = transfer_request.session.transaction_hash; builder.exec(transfer_request).commit().expect_success(); @@ -221,28 +191,27 @@ fn should_record_wasm_transfer_with_id() { .main_purse() .with_access_rights(AccessRights::ADD); - let deploy_info = builder - .get_deploy_info(deploy_hash) - .expect("should have deploy info"); - - assert_eq!(deploy_info.deploy_hash, deploy_hash); - assert_eq!(deploy_info.from, *DEFAULT_ACCOUNT_ADDR); - assert_eq!(deploy_info.source, default_account.main_purse()); - assert_ne!(deploy_info.gas, U512::zero()); + let execution_result = builder + .get_last_exec_result() + .expect("Expected execution results."); - let transfers = deploy_info.transfers; + assert_ne!(execution_result.consumed(), Gas::zero()); + let transfers = execution_result.transfers(); assert_eq!(transfers.len(), 1); - let transfer = builder - .get_transfer(transfers[0]) - .expect("should have transfer"); + let Transfer::V2(transfer) = transfers[0].clone() else { + panic!("wrong transfer variant"); + }; - assert_eq!(transfer.deploy_hash, deploy_hash); - assert_eq!(transfer.from, *DEFAULT_ACCOUNT_ADDR); + assert_eq!(transfer.transaction_hash, txn_hash); + assert_eq!( + transfer.from, + InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR) + ); assert_eq!(transfer.source, default_account.main_purse()); assert_eq!(transfer.target, alice_attenuated_main_purse); assert_eq!(transfer.amount, *TRANSFER_AMOUNT_1); - assert_eq!(transfer.gas, U512::zero()); // TODO + assert_eq!(transfer.gas, Gas::zero()); // TODO assert_eq!(transfer.id, id); } @@ -250,7 +219,7 @@ fn should_record_wasm_transfer_with_id() { #[test] fn should_record_wasm_transfers() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let alice_id = Some(0); let bob_id = Some(1); @@ -274,14 +243,7 @@ fn should_record_wasm_transfers() { ) .build(); - let deploy_hash = { - let deploy_items: Vec = transfer_request - .deploys() - .iter() - .map(|deploy_item| deploy_item.deploy_hash) - .collect(); - deploy_items[0] - }; + let txn_hash = transfer_request.session.transaction_hash; builder.exec(transfer_request).commit().expect_success(); @@ -313,79 +275,72 @@ fn should_record_wasm_transfers() { .main_purse() .with_access_rights(AccessRights::ADD); - let deploy_info = builder - .get_deploy_info(deploy_hash) - .expect("should have deploy info"); - - assert_eq!(deploy_info.deploy_hash, deploy_hash); - assert_eq!(deploy_info.from, *DEFAULT_ACCOUNT_ADDR); - assert_eq!(deploy_info.source, default_account.main_purse()); - assert_ne!(deploy_info.gas, U512::zero()); + let execution_result = builder + .get_last_exec_result() + .expect("Expected execution results."); + assert_ne!(execution_result.consumed(), Gas::zero()); const EXPECTED_LENGTH: usize = 3; - let transfer_addrs = deploy_info.transfers; - assert_eq!(transfer_addrs.len(), EXPECTED_LENGTH); + assert_eq!(execution_result.transfers().len(), EXPECTED_LENGTH); assert_eq!( - transfer_addrs + execution_result + .transfers() .iter() .cloned() - .collect::>() + .collect::>() .len(), EXPECTED_LENGTH ); let transfers: BTreeSet = { let mut tmp = BTreeSet::new(); - for transfer_addr in transfer_addrs { - let transfer = builder - .get_transfer(transfer_addr) - .expect("should have transfer"); - tmp.insert(transfer); + for transfer in execution_result.transfers() { + tmp.insert(transfer.clone()); } tmp }; assert_eq!(transfers.len(), EXPECTED_LENGTH); - assert!(transfers.contains(&Transfer { - deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + assert!(transfers.contains(&Transfer::V2(TransferV2 { + transaction_hash: txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*ALICE_ADDR), source: default_account.main_purse(), target: alice_attenuated_main_purse, amount: *TRANSFER_AMOUNT_1, - gas: U512::zero(), + gas: Gas::zero(), id: alice_id, - })); + }))); - assert!(transfers.contains(&Transfer { - deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + assert!(transfers.contains(&Transfer::V2(TransferV2 { + transaction_hash: txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*BOB_ADDR), source: default_account.main_purse(), target: bob_attenuated_main_purse, amount: *TRANSFER_AMOUNT_2, - gas: U512::zero(), + gas: Gas::zero(), id: bob_id, - })); + }))); - assert!(transfers.contains(&Transfer { - deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + assert!(transfers.contains(&Transfer::V2(TransferV2 { + transaction_hash: txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*CAROL_ADDR), source: default_account.main_purse(), target: carol_attenuated_main_purse, amount: *TRANSFER_AMOUNT_3, - gas: U512::zero(), + gas: Gas::zero(), id: carol_id, - })); + }))); } #[ignore] #[test] fn should_record_wasm_transfers_with_subcall() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let alice_id = Some(0); let bob_id = Some(1); @@ -420,14 +375,7 @@ fn should_record_wasm_transfers_with_subcall() { ) .build(); - let transfer_deploy_hash = { - let deploy_items: Vec = transfer_request - .deploys() - .iter() - .map(|deploy_item| deploy_item.deploy_hash) - .collect(); - deploy_items[0] - }; + let transfer_txn_hash = transfer_request.session.transaction_hash; builder.exec(store_request).commit().expect_success(); builder.exec(transfer_request).commit().expect_success(); @@ -478,70 +426,74 @@ fn should_record_wasm_transfers_with_subcall() { .main_purse() .with_access_rights(AccessRights::ADD); - let deploy_info = builder - .get_deploy_info(transfer_deploy_hash) - .expect("should have deploy info"); + let execution_result = builder + .get_last_exec_result() + .expect("Expected execution results."); - assert_eq!(deploy_info.deploy_hash, transfer_deploy_hash); - assert_eq!(deploy_info.from, *DEFAULT_ACCOUNT_ADDR); - assert_eq!(deploy_info.source, default_account.main_purse()); - assert_ne!(deploy_info.gas, U512::zero()); + /* + assert_eq!(txn_info.transaction_hash, transfer_txn_hash); + assert_eq!( + txn_info.from, + InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR) + ); + assert_eq!(txn_info.source, default_account.main_purse()); + */ + assert_ne!(execution_result.consumed(), Gas::zero()); const EXPECTED_LENGTH: usize = 6; - let transfer_addrs = deploy_info.transfers; - assert_eq!(transfer_addrs.len(), EXPECTED_LENGTH); + assert_eq!(execution_result.transfers().len(), EXPECTED_LENGTH); assert_eq!( - transfer_addrs + execution_result + .transfers() .iter() .cloned() - .collect::>() + .collect::>() .len(), EXPECTED_LENGTH ); let transfer_counts: BTreeMap = { let mut tmp = BTreeMap::new(); - for transfer_addr in transfer_addrs { - let transfer = builder - .get_transfer(transfer_addr) - .expect("should have transfer"); - tmp.entry(transfer).and_modify(|i| *i += 1).or_insert(1); + for transfer in execution_result.transfers() { + tmp.entry(transfer.clone()) + .and_modify(|i| *i += 1) + .or_insert(1); } tmp }; - let session_expected_alice = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let session_expected_alice = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*ALICE_ADDR), source: default_account.main_purse(), target: alice_attenuated_main_purse, amount: *TRANSFER_AMOUNT_1, - gas: U512::zero(), + gas: Gas::zero(), id: alice_id, - }; + }); - let session_expected_bob = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let session_expected_bob = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*BOB_ADDR), source: default_account.main_purse(), target: bob_attenuated_main_purse, amount: *TRANSFER_AMOUNT_2, - gas: U512::zero(), + gas: Gas::zero(), id: bob_id, - }; + }); - let session_expected_carol = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let session_expected_carol = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*CAROL_ADDR), source: default_account.main_purse(), target: carol_attenuated_main_purse, amount: *TRANSFER_AMOUNT_3, - gas: U512::zero(), + gas: Gas::zero(), id: carol_id, - }; + }); const SESSION_EXPECTED_COUNT: Option = Some(1); for (i, expected) in [ @@ -560,38 +512,38 @@ fn should_record_wasm_transfers_with_subcall() { ); } - let stored_expected_alice = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let stored_expected_alice = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*ALICE_ADDR), source: contract_purse, target: alice_attenuated_main_purse, amount: *TRANSFER_AMOUNT_1, - gas: U512::zero(), + gas: Gas::zero(), id: alice_id, - }; + }); - let stored_expected_bob = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let stored_expected_bob = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*BOB_ADDR), source: contract_purse, target: bob_attenuated_main_purse, amount: *TRANSFER_AMOUNT_2, - gas: U512::zero(), + gas: Gas::zero(), id: bob_id, - }; + }); - let stored_expected_carol = Transfer { - deploy_hash: transfer_deploy_hash, - from: *DEFAULT_ACCOUNT_ADDR, + let stored_expected_carol = Transfer::V2(TransferV2 { + transaction_hash: transfer_txn_hash, + from: InitiatorAddr::AccountHash(*DEFAULT_ACCOUNT_ADDR), to: Some(*CAROL_ADDR), source: contract_purse, target: carol_attenuated_main_purse, amount: *TRANSFER_AMOUNT_3, - gas: U512::zero(), + gas: Gas::zero(), id: carol_id, - }; + }); const STORED_EXPECTED_COUNT: Option = Some(1); for (i, expected) in [ diff --git a/execution_engine_testing/tests/src/test/deploy/stored_contracts.rs b/execution_engine_testing/tests/src/test/deploy/stored_contracts.rs index 65f0d8f668..9d1e449407 100644 --- a/execution_engine_testing/tests/src/test/deploy/stored_contracts.rs +++ b/execution_engine_testing/tests/src/test/deploy/stored_contracts.rs @@ -2,13 +2,12 @@ use assert_matches::assert_matches; use casper_engine_test_support::{ DeployItemBuilder, EntityWithNamedKeys, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, - DEFAULT_ACCOUNT_KEY, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_KEY, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ - account::AccountHash, - package::{EntityVersion, ENTITY_INITIAL_VERSION}, - runtime_args, EntityVersionKey, EraId, PackageHash, ProtocolVersion, RuntimeArgs, U512, + account::AccountHash, runtime_args, EntityVersion, EntityVersionKey, EraId, PackageHash, + ProtocolVersion, RuntimeArgs, ENTITY_INITIAL_VERSION, U512, }; const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([42u8; 32]); @@ -61,7 +60,7 @@ fn install_custom_payment( .into_package_hash() .expect("should be a hash"); - let exec_cost = builder.last_exec_result().cost().value(); + let exec_cost = builder.get_last_exec_result().unwrap().consumed().value(); (default_account, package_hash, exec_cost) } @@ -76,28 +75,26 @@ fn should_exec_non_stored_code() { let payment_purse_amount = *DEFAULT_PAYMENT; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code( - format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), - runtime_args! { - ARG_TARGET => account_1_account_hash, - ARG_AMOUNT => U512::from(transferred_amount) - }, - ) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_purse_amount, - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([1; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code( + format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), + runtime_args! { + ARG_TARGET => account_1_account_hash, + ARG_AMOUNT => U512::from(transferred_amount) + }, + ) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_purse_amount, + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([1; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); @@ -126,12 +123,13 @@ fn should_exec_non_stored_code() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_fail_if_calling_non_existent_entry_point() { let payment_purse_amount = *DEFAULT_PAYMENT; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // first, store payment contract with entry point named "pay" let exec_request = ExecuteRequestBuilder::standard( @@ -155,21 +153,19 @@ fn should_fail_if_calling_non_existent_entry_point() { // next make another deploy that attempts to use the stored payment logic // but passing the name for an entry point that does not exist. - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code(format!("{}.wasm", DO_NOTHING_NAME), RuntimeArgs::default()) - .with_stored_payment_hash( - stored_payment_contract_hash.into(), - "electric-boogaloo", - runtime_args! { ARG_AMOUNT => payment_purse_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([1; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code(format!("{}.wasm", DO_NOTHING_NAME), RuntimeArgs::default()) + .with_stored_payment_hash( + stored_payment_contract_hash.into(), + "electric-boogaloo", + runtime_args! { ARG_AMOUNT => payment_purse_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([1; 32]) + .build(); + + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).commit(); @@ -184,13 +180,14 @@ fn should_fail_if_calling_non_existent_entry_point() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_exec_stored_code_by_hash() { let default_payment = *DEFAULT_PAYMENT; // genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store payment let (sending_account, custom_payment_package_hash, _) = install_custom_payment(&mut builder); @@ -210,27 +207,26 @@ fn should_exec_stored_code_by_hash() { // next make another deploy that USES stored payment logic { - let transfer_using_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_payment_contract_by_hash( - custom_payment_package_hash.value(), - Some(ENTITY_INITIAL_VERSION), - PAY_ENTRYPOINT, - runtime_args! { - ARG_AMOUNT => default_payment, - }, - ) - .with_session_code( - format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), - runtime_args! { ARG_TARGET => ACCOUNT_1_ADDR, ARG_AMOUNT => transferred_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_payment_contract_by_hash( + custom_payment_package_hash.value(), + Some(ENTITY_INITIAL_VERSION), + PAY_ENTRYPOINT, + runtime_args! { + ARG_AMOUNT => default_payment, + }, + ) + .with_session_code( + format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), + runtime_args! { ARG_TARGET => ACCOUNT_1_ADDR, ARG_AMOUNT => transferred_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let transfer_using_stored_payment = + ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(transfer_using_stored_payment).expect_failure(); } @@ -241,13 +237,14 @@ fn should_exec_stored_code_by_hash() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_transfer_above_balance_using_stored_payment_code_by_hash() { let payment_purse_amount = *DEFAULT_PAYMENT; // genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store payment let (default_account, hash, _) = install_custom_payment(&mut builder); @@ -255,9 +252,8 @@ fn should_not_transfer_above_balance_using_stored_payment_code_by_hash() { let transferred_amount = starting_balance - *DEFAULT_PAYMENT + U512::one(); - let exec_request_stored_payment = { - let account_1_account_hash = ACCOUNT_1_ADDR; - let deploy = DeployItemBuilder::new() + let account_1_account_hash = ACCOUNT_1_ADDR; + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code( format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), @@ -275,8 +271,7 @@ fn should_not_transfer_above_balance_using_stored_payment_code_by_hash() { .with_deploy_hash([2; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(exec_request_stored_payment) @@ -289,13 +284,14 @@ fn should_not_transfer_above_balance_using_stored_payment_code_by_hash() { } #[ignore] +#[allow(unused)] #[test] fn should_empty_account_using_stored_payment_code_by_hash() { let payment_purse_amount = *DEFAULT_PAYMENT; // genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store payment @@ -307,9 +303,8 @@ fn should_empty_account_using_stored_payment_code_by_hash() { let transferred_amount = starting_balance - *DEFAULT_PAYMENT; { - let exec_request_stored_payment = { - let account_1_account_hash = ACCOUNT_1_ADDR; - let deploy = DeployItemBuilder::new() + let account_1_account_hash = ACCOUNT_1_ADDR; + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code( format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), @@ -327,8 +322,8 @@ fn should_empty_account_using_stored_payment_code_by_hash() { .with_deploy_hash([2; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request_stored_payment = + ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).expect_failure(); } @@ -339,13 +334,14 @@ fn should_empty_account_using_stored_payment_code_by_hash() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_exec_stored_code_by_named_hash() { let payment_purse_amount = *DEFAULT_PAYMENT; // genesis let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); install_custom_payment(&mut builder); @@ -354,9 +350,8 @@ fn should_exec_stored_code_by_named_hash() { let transferred_amount = 1; { - let exec_request_stored_payment = { - let account_1_account_hash = ACCOUNT_1_ADDR; - let deploy = DeployItemBuilder::new() + let account_1_account_hash = ACCOUNT_1_ADDR; + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code( format!("{}.wasm", TRANSFER_PURSE_TO_ACCOUNT_CONTRACT_NAME), @@ -374,8 +369,8 @@ fn should_exec_stored_code_by_named_hash() { .with_deploy_hash([2; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request_stored_payment = + ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).expect_failure(); @@ -400,7 +395,7 @@ fn should_fail_payment_stored_at_hash_with_incompatible_major_version() { .build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).expect_success().commit(); @@ -438,24 +433,19 @@ fn should_fail_payment_stored_at_hash_with_incompatible_major_version() { .expect_upgrade_success(); // next make another deploy that USES stored payment logic - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code(format!("{}.wasm", DO_NOTHING_NAME), RuntimeArgs::default()) - .with_stored_payment_hash( - stored_payment_contract_hash.into(), - PAY_ENTRYPOINT, - runtime_args! { ARG_AMOUNT => payment_purse_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(new_protocol_version) - .build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code(format!("{}.wasm", DO_NOTHING_NAME), RuntimeArgs::default()) + .with_stored_payment_hash( + stored_payment_contract_hash.into(), + PAY_ENTRYPOINT, + runtime_args! { ARG_AMOUNT => payment_purse_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); + + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).commit(); @@ -478,7 +468,7 @@ fn should_fail_session_stored_at_named_key_with_incompatible_major_version() { let payment_purse_amount = *DEFAULT_PAYMENT; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // first, store payment contract for v1.0.0 let exec_request_1 = ExecuteRequestBuilder::standard( @@ -489,7 +479,7 @@ fn should_fail_session_stored_at_named_key_with_incompatible_major_version() { .build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).commit(); @@ -533,28 +523,23 @@ fn should_fail_session_stored_at_named_key_with_incompatible_major_version() { // Call stored session code - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_session_named_key( - DO_NOTHING_CONTRACT_HASH_NAME, - ENTRY_FUNCTION_NAME, - RuntimeArgs::new(), - ) - .with_stored_payment_hash( - stored_payment_contract_hash.into(), - PAY_ENTRYPOINT, - runtime_args! { ARG_AMOUNT => payment_purse_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(new_protocol_version) - .build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_session_named_key( + DO_NOTHING_CONTRACT_HASH_NAME, + ENTRY_FUNCTION_NAME, + RuntimeArgs::new(), + ) + .with_stored_payment_hash( + stored_payment_contract_hash.into(), + PAY_ENTRYPOINT, + runtime_args! { ARG_AMOUNT => payment_purse_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); + + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).commit(); @@ -573,7 +558,8 @@ fn should_fail_session_stored_at_named_key_with_incompatible_major_version() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_fail_session_stored_at_named_key_with_missing_new_major_version() { let payment_purse_amount = *DEFAULT_PAYMENT; @@ -586,7 +572,7 @@ fn should_fail_session_stored_at_named_key_with_missing_new_major_version() { .build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).commit(); @@ -615,30 +601,25 @@ fn should_fail_session_stored_at_named_key_with_missing_new_major_version() { // Call stored session code - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - DO_NOTHING_CONTRACT_PACKAGE_HASH_NAME, - Some(INITIAL_VERSION), - ENTRY_FUNCTION_NAME, - RuntimeArgs::new(), - ) - .with_payment_code( - STORED_PAYMENT_CONTRACT_NAME, - runtime_args! { - ARG_AMOUNT => payment_purse_amount, - }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + DO_NOTHING_CONTRACT_PACKAGE_HASH_NAME, + Some(INITIAL_VERSION), + ENTRY_FUNCTION_NAME, + RuntimeArgs::new(), + ) + .with_payment_code( + STORED_PAYMENT_CONTRACT_NAME, + runtime_args! { + ARG_AMOUNT => payment_purse_amount, + }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(new_protocol_version) - .build() - }; + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).commit(); @@ -660,7 +641,7 @@ fn should_fail_session_stored_at_hash_with_incompatible_major_version() { let payment_purse_amount = *DEFAULT_PAYMENT; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // first, store payment contract for v1.0.0 let exec_request_1 = ExecuteRequestBuilder::standard( @@ -671,7 +652,7 @@ fn should_fail_session_stored_at_hash_with_incompatible_major_version() { .build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).commit(); @@ -710,28 +691,23 @@ fn should_fail_session_stored_at_hash_with_incompatible_major_version() { .into_entity_hash_addr() .expect("standard_payment named key should be hash"); - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_session_named_key( - DO_NOTHING_CONTRACT_HASH_NAME, - ENTRY_FUNCTION_NAME, - RuntimeArgs::new(), - ) - .with_stored_payment_hash( - test_payment_stored_hash.into(), - PAY_ENTRYPOINT, - runtime_args! { ARG_AMOUNT => payment_purse_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(new_protocol_version) - .build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_session_named_key( + DO_NOTHING_CONTRACT_HASH_NAME, + ENTRY_FUNCTION_NAME, + RuntimeArgs::new(), + ) + .with_stored_payment_hash( + test_payment_stored_hash.into(), + PAY_ENTRYPOINT, + runtime_args! { ARG_AMOUNT => payment_purse_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); + + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_stored_payment).commit(); @@ -754,12 +730,13 @@ fn should_fail_session_stored_at_hash_with_incompatible_major_version() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_execute_stored_payment_and_session_code_with_new_major_version() { let payment_purse_amount = *DEFAULT_PAYMENT; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // // upgrade with new wasm costs with modified mint for given version @@ -781,7 +758,6 @@ fn should_execute_stored_payment_and_session_code_with_new_major_version() { STORED_PAYMENT_CONTRACT_NAME, RuntimeArgs::default(), ) - .with_protocol_version(new_protocol_version) .build(); let exec_request_2 = ExecuteRequestBuilder::standard( @@ -789,7 +765,6 @@ fn should_execute_stored_payment_and_session_code_with_new_major_version() { &format!("{}_stored.wasm", DO_NOTHING_NAME), RuntimeArgs::default(), ) - .with_protocol_version(new_protocol_version) .build(); // store both contracts @@ -808,29 +783,24 @@ fn should_execute_stored_payment_and_session_code_with_new_major_version() { .into_entity_hash_addr() .expect("standard_payment named key should be hash"); - let exec_request_stored_payment = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - DO_NOTHING_CONTRACT_PACKAGE_HASH_NAME, - Some(INITIAL_VERSION), - ENTRY_FUNCTION_NAME, - RuntimeArgs::new(), - ) - .with_stored_payment_hash( - test_payment_stored_hash.into(), - PAY_ENTRYPOINT, - runtime_args! { ARG_AMOUNT => payment_purse_amount }, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(new_protocol_version) - .build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + DO_NOTHING_CONTRACT_PACKAGE_HASH_NAME, + Some(INITIAL_VERSION), + ENTRY_FUNCTION_NAME, + RuntimeArgs::new(), + ) + .with_stored_payment_hash( + test_payment_stored_hash.into(), + PAY_ENTRYPOINT, + runtime_args! { ARG_AMOUNT => payment_purse_amount }, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_stored_payment = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .clear_results() diff --git a/execution_engine_testing/tests/src/test/explorer/faucet.rs b/execution_engine_testing/tests/src/test/explorer/faucet.rs index 3845f0d016..9bfbc94020 100644 --- a/execution_engine_testing/tests/src/test/explorer/faucet.rs +++ b/execution_engine_testing/tests/src/test/explorer/faucet.rs @@ -3,12 +3,12 @@ use num_rational::Ratio; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + ChainspecConfig, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, + TransferRequestBuilder, CHAINSPEC_SYMLINK, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{ - account::AccountHash, addressable_entity::EntityKindTag, runtime_args, system::mint, ApiError, - Key, PublicKey, SecretKey, U512, + account::AccountHash, addressable_entity::EntityKindTag, runtime_args, ApiError, FeeHandling, + Key, PricingHandling, PublicKey, RefundHandling, SecretKey, U512, }; // test constants. @@ -34,7 +34,7 @@ const FAUCET_CALL_BY_USER_WITH_AUTHORIZED_ACCOUNT_SET: u16 = 25; #[test] fn should_install_faucet_contract() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let fund_installer_account_request = FundAccountRequestBuilder::new() .with_target_account(INSTALLER_ACCOUNT) @@ -42,14 +42,11 @@ fn should_install_faucet_contract() { .build(); builder - .exec(fund_installer_account_request) - .expect_success() - .commit(); - - let install_faucet_request = FaucetInstallSessionRequestBuilder::new().build(); + .transfer_and_commit(fund_installer_account_request) + .expect_success(); builder - .exec(install_faucet_request) + .exec(FaucetInstallSessionRequestBuilder::new().build()) .expect_success() .commit(); @@ -133,7 +130,7 @@ fn should_install_faucet_contract() { #[test] fn should_allow_installer_to_set_variables() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut helper = FaucetDeployHelper::new() .with_installer_account(INSTALLER_ACCOUNT) @@ -144,9 +141,8 @@ fn should_allow_installer_to_set_variables() { .with_faucet_time_interval(Some(FAUCET_TIME_INTERVAL)); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -227,7 +223,7 @@ fn should_allow_installer_to_set_variables() { fn should_fund_new_account() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let faucet_purse_fund_amount = U512::from(9_000_000_000u64); let faucet_distributions_per_interval = 3; @@ -238,9 +234,8 @@ fn should_fund_new_account() { .with_faucet_distributions_per_interval(Some(faucet_distributions_per_interval)); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -289,12 +284,13 @@ fn should_fund_new_account() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_fund_existing_account() { let user_account = AccountHash::new([7u8; 32]); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let faucet_purse_fund_amount = U512::from(9_000_000_000u64); let faucet_distributions_per_interval = 3; @@ -305,9 +301,8 @@ fn should_fund_existing_account() { .with_faucet_distributions_per_interval(Some(faucet_distributions_per_interval)); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); let user_account_initial_balance = U512::from(15_000_000_000u64); @@ -316,7 +311,9 @@ fn should_fund_existing_account() { .with_fund_amount(user_account_initial_balance) .build(); - builder.exec(fund_user_request).expect_success().commit(); + builder + .transfer_and_commit(fund_user_request) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -361,13 +358,14 @@ fn should_fund_existing_account() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_fund_once_exhausted() { let installer_account = AccountHash::new([1u8; 32]); let user_account = AccountHash::new([2u8; 32]); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let faucet_fund_amount = U512::from(400_000_000_000_000u64); let half_of_faucet_fund_amount = faucet_fund_amount / 2; @@ -383,9 +381,8 @@ fn should_not_fund_once_exhausted() { // fund installer amount builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); // faucet install request builder @@ -565,7 +562,7 @@ fn should_allow_installer_to_fund_freely() { let user_account = AccountHash::new([2u8; 32]); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let faucet_fund_amount = U512::from(200_000_000_000u64); let half_of_faucet_fund_amount = faucet_fund_amount / 2; @@ -579,9 +576,8 @@ fn should_allow_installer_to_fund_freely() { .with_faucet_time_interval(Some(10_000u64)); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -665,7 +661,7 @@ fn should_not_fund_if_zero_distributions_per_interval() { let user_account = AccountHash::new([2u8; 32]); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Fund installer account let fund_installer_account_request = FundAccountRequestBuilder::new() @@ -674,9 +670,8 @@ fn should_not_fund_if_zero_distributions_per_interval() { .build(); builder - .exec(fund_installer_account_request) - .expect_success() - .commit(); + .transfer_and_commit(fund_installer_account_request) + .expect_success(); let faucet_fund_amount = U512::from(400_000_000_000_000u64); @@ -723,7 +718,7 @@ fn should_allow_funding_by_an_authorized_account() { let half_of_faucet_fund_amount = faucet_fund_amount / 2; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut helper = FaucetDeployHelper::new() .with_installer_account(installer_account) @@ -734,9 +729,8 @@ fn should_allow_funding_by_an_authorized_account() { .with_faucet_time_interval(Some(10_000u64)); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -845,16 +839,11 @@ fn should_allow_funding_by_an_authorized_account() { .expect_failure() .commit(); - let exec_results = builder + let exec_result = builder .get_last_exec_result() .expect("failed to get exec results"); - let exec_result = exec_results - .first() - .expect("an exec result must exist") - .clone(); - - let error = exec_result.as_error().unwrap(); + let error = exec_result.error().unwrap(); assert!( matches!( error, @@ -868,20 +857,20 @@ fn should_allow_funding_by_an_authorized_account() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_refund_proper_amount() { let user_account = AccountHash::new([7u8; 32]); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let payment_amount = U512::from(10_000_000_000u64); let mut helper = FaucetDeployHelper::default(); builder - .exec(helper.fund_installer_request()) - .expect_success() - .commit(); + .transfer_and_commit(helper.fund_installer_request()) + .expect_success(); let user_account_initial_balance = U512::from(15_000_000_000u64); @@ -890,7 +879,9 @@ fn should_refund_proper_amount() { .with_fund_amount(user_account_initial_balance) .build(); - builder.exec(fund_user_request).expect_success().commit(); + builder + .transfer_and_commit(fund_user_request) + .expect_success(); builder .exec(helper.faucet_install_request()) @@ -935,31 +926,30 @@ fn faucet_costs() { // This test will fail if execution costs vary. The expected costs should not be updated // without understanding why the cost has changed. If the costs do change, it should be // reflected in the "Costs by Entry Point" section of the faucet crate's README.md. - const EXPECTED_FAUCET_INSTALL_COST: u64 = 91_060_413_740; - const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_328_060; - const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_774_897_300; - const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_855_200; + const EXPECTED_FAUCET_INSTALL_COST: u64 = 91_914_271_090; + const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_340_630; + const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_774_911_250; + const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_882_230; let installer_account = AccountHash::new([1u8; 32]); let user_account: AccountHash = AccountHash::new([2u8; 32]); + let chainspec = ChainspecConfig::from_chainspec_path(&*CHAINSPEC_SYMLINK) + .expect("must build chainspec configuration"); + let chainspec_config = chainspec + .with_fee_handling(FeeHandling::NoFee) + .with_refund_handling(RefundHandling::NoRefund) + .with_pricing_handling(PricingHandling::Fixed); + LmdbWasmTestBuilder::new_temporary_with_config(chainspec_config); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let fund_installer_account_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => installer_account, - mint::ARG_AMOUNT => INSTALLER_FUND_AMOUNT, - mint::ARG_ID => >::None - }, - ) - .build(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let fund_installer_account_request = + TransferRequestBuilder::new(INSTALLER_FUND_AMOUNT, installer_account).build(); builder - .exec(fund_installer_account_request) - .expect_success() - .commit(); + .transfer_and_commit(fund_installer_account_request) + .expect_success(); let faucet_fund_amount = U512::from(400_000_000_000_000u64); let installer_session_request = ExecuteRequestBuilder::standard( @@ -978,25 +968,24 @@ fn faucet_costs() { let assigned_time_interval = 10_000u64; let assigned_distributions_per_interval = 2u64; - let installer_set_variable_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(installer_account) - .with_authorization_keys(&[installer_account]) - .with_stored_session_named_key( - &format!("{}_{}", FAUCET_CONTRACT_NAMED_KEY, FAUCET_ID), - ENTRY_POINT_SET_VARIABLES, - runtime_args! { - ARG_AVAILABLE_AMOUNT => Some(faucet_fund_amount), - ARG_TIME_INTERVAL => Some(assigned_time_interval), - ARG_DISTRIBUTIONS_PER_INTERVAL => Some(assigned_distributions_per_interval) - }, - ) - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) - .with_deploy_hash([3; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(installer_account) + .with_authorization_keys(&[installer_account]) + .with_stored_session_named_key( + &format!("{}_{}", FAUCET_CONTRACT_NAMED_KEY, FAUCET_ID), + ENTRY_POINT_SET_VARIABLES, + runtime_args! { + ARG_AVAILABLE_AMOUNT => Some(faucet_fund_amount), + ARG_TIME_INTERVAL => Some(assigned_time_interval), + ARG_DISTRIBUTIONS_PER_INTERVAL => Some(assigned_distributions_per_interval) + }, + ) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_deploy_hash([3; 32]) + .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let installer_set_variable_request = + ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(installer_set_variable_request) @@ -1006,8 +995,8 @@ fn faucet_costs() { let faucet_set_variables_cost = builder.last_exec_gas_cost(); let user_fund_amount = U512::from(10_000_000_000u64); - let faucet_call_by_installer = { - let deploy_item = DeployItemBuilder::new() + + let deploy_item = DeployItemBuilder::new() .with_address(installer_account) .with_authorization_keys(&[installer_account]) .with_stored_session_named_key( @@ -1015,12 +1004,11 @@ fn faucet_costs() { ENTRY_POINT_FAUCET, runtime_args! {ARG_TARGET => user_account, ARG_AMOUNT => user_fund_amount, ARG_ID => >::None}, ) - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => *DEFAULT_PAYMENT}) .with_deploy_hash([4; 32]) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let faucet_call_by_installer = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(faucet_call_by_installer) @@ -1031,21 +1019,19 @@ fn faucet_costs() { let faucet_contract_hash = get_faucet_entity_hash(&builder, installer_account); - let faucet_call_by_user_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(user_account) - .with_authorization_keys(&[user_account]) - .with_stored_session_hash( - faucet_contract_hash, - ENTRY_POINT_FAUCET, - runtime_args! {ARG_TARGET => user_account, ARG_ID => >::None}, - ) - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => user_fund_amount}) - .with_deploy_hash([4; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(user_account) + .with_authorization_keys(&[user_account]) + .with_stored_session_hash( + faucet_contract_hash, + ENTRY_POINT_FAUCET, + runtime_args! {ARG_TARGET => user_account, ARG_ID => >::None}, + ) + .with_standard_payment(runtime_args! {ARG_AMOUNT => user_fund_amount}) + .with_deploy_hash([4; 32]) + .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let faucet_call_by_user_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(faucet_call_by_user_request) diff --git a/execution_engine_testing/tests/src/test/explorer/faucet_test_helpers.rs b/execution_engine_testing/tests/src/test/explorer/faucet_test_helpers.rs index e31a2cfd77..c78209c35a 100644 --- a/execution_engine_testing/tests/src/test/explorer/faucet_test_helpers.rs +++ b/execution_engine_testing/tests/src/test/explorer/faucet_test_helpers.rs @@ -1,13 +1,13 @@ use rand::Rng; use casper_engine_test_support::{ - DeployItemBuilder, EntityWithNamedKeys, ExecuteRequestBuilder, LmdbWasmTestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, + DeployItemBuilder, EntityWithNamedKeys, ExecuteRequest, ExecuteRequestBuilder, + LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_PAYMENT, }; -use casper_execution_engine::engine_state::ExecuteRequest; +use casper_storage::data_access_layer::TransferRequest; use casper_types::{ account::AccountHash, addressable_entity::EntityKindTag, bytesrepr::FromBytes, runtime_args, - system::mint, AddressableEntityHash, CLTyped, Key, PublicKey, URef, U512, + AddressableEntityHash, CLTyped, Key, PublicKey, URef, U512, }; use super::{ @@ -45,16 +45,12 @@ impl FundAccountRequestBuilder { self } - pub fn build(&self) -> ExecuteRequest { - ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => self.target_account, - mint::ARG_AMOUNT => self.fund_amount, - mint::ARG_ID => self.fund_id - }, - ) - .build() + pub fn build(&self) -> TransferRequest { + let mut builder = TransferRequestBuilder::new(self.fund_amount, self.target_account); + if let Some(id) = self.fund_id { + builder = builder.with_transfer_id(id); + } + builder.build() } } @@ -341,15 +337,15 @@ impl FaucetFundRequestBuilder { }, }, ) - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => self.payment_amount}) + .with_standard_payment(runtime_args! {ARG_AMOUNT => self.payment_amount}) .with_deploy_hash(rng.gen()) .build(); match self.block_time { - Some(block_time) => ExecuteRequestBuilder::from_deploy_item(deploy_item) + Some(block_time) => ExecuteRequestBuilder::from_deploy_item(&deploy_item) .with_block_time(block_time) .build(), - None => ExecuteRequestBuilder::from_deploy_item(deploy_item).build(), + None => ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(), } } } @@ -551,7 +547,7 @@ impl FaucetDeployHelper { self.faucet_time_interval } - pub fn fund_installer_request(&self) -> ExecuteRequest { + pub fn fund_installer_request(&self) -> TransferRequest { self.fund_account_request_builder .with_target_account(self.installer_account) .with_fund_amount(self.installer_fund_amount) diff --git a/execution_engine_testing/tests/src/test/gas_counter.rs b/execution_engine_testing/tests/src/test/gas_counter.rs index 86068a00e7..605505c417 100644 --- a/execution_engine_testing/tests/src/test/gas_counter.rs +++ b/execution_engine_testing/tests/src/test/gas_counter.rs @@ -6,7 +6,7 @@ use casper_wasm::{ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, DEFAULT_WASM_CONFIG, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, DEFAULT_WASM_CONFIG, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, runtime::PreprocessingError}; use casper_types::{addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, Gas, RuntimeArgs}; @@ -43,29 +43,25 @@ fn should_fail_to_overflow_gas_counter() { let session_bytes = make_gas_counter_overflow(); - let exec_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(session_bytes, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(session_bytes, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let responses = builder + let exec_result = builder .get_exec_result_owned(0) .expect("should have response"); - let response = responses.get(0).expect("should have first element"); - - let lhs = response.as_error().expect("should have error"); + let lhs = exec_result.error().expect("should have error"); assert_matches!( lhs, Error::WasmPreprocessing(PreprocessingError::OperationForbiddenByGasRules) @@ -151,20 +147,18 @@ fn should_correctly_measure_gas_for_opcodes() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let exec_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(session_bytes, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(session_bytes, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit().expect_success(); diff --git a/execution_engine_testing/tests/src/test/get_balance.rs b/execution_engine_testing/tests/src/test/get_balance.rs index 29e87c3bfd..c324cbc085 100644 --- a/execution_engine_testing/tests/src/test/get_balance.rs +++ b/execution_engine_testing/tests/src/test/get_balance.rs @@ -1,19 +1,17 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + LmdbWasmTestBuilder, TransferRequestBuilder, LOCAL_GENESIS_REQUEST, +}; +use casper_storage::{ + data_access_layer::BalanceIdentifier, + tracking_copy::{self, ValidationError}, }; -use casper_storage::tracking_copy::{self, ValidationError}; use casper_types::{ - account::AccountHash, runtime_args, AccessRights, Digest, Key, ProtocolVersion, PublicKey, - SecretKey, URef, U512, + account::AccountHash, AccessRights, Digest, Key, ProtocolVersion, PublicKey, SecretKey, URef, + U512, }; -const TRANSFER_ARG_TARGET: &str = "target"; -const TRANSFER_ARG_AMOUNT: &str = "amount"; -const TRANSFER_ARG_ID: &str = "id"; - static ALICE_KEY: Lazy = Lazy::new(|| { let secret_key = SecretKey::ed25519_from_bytes([3; SecretKey::ED25519_LENGTH]).unwrap(); PublicKey::from(&secret_key) @@ -27,19 +25,16 @@ static TRANSFER_AMOUNT_1: Lazy = Lazy::new(|| U512::from(100_000_000)); fn get_balance_should_work() { let protocol_version = ProtocolVersion::V2_0_0; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - TRANSFER_ARG_TARGET => *ALICE_ADDR, - TRANSFER_ARG_AMOUNT => *TRANSFER_AMOUNT_1, - TRANSFER_ARG_ID => >::None, - }, - ) - .build(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let block_time = 1_000_000; + let transfer_request = TransferRequestBuilder::new(*TRANSFER_AMOUNT_1, *ALICE_ADDR) + .with_block_time(block_time) + .build(); - builder.exec(transfer_request).commit().expect_success(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let alice_account = builder .get_entity_by_account_hash(*ALICE_ADDR) @@ -47,7 +42,11 @@ fn get_balance_should_work() { let alice_main_purse = alice_account.main_purse(); - let alice_balance_result = builder.get_purse_balance_result(protocol_version, alice_main_purse); + let alice_balance_result = builder.get_purse_balance_result( + protocol_version, + BalanceIdentifier::Purse(alice_main_purse), + block_time, + ); let alice_balance = alice_balance_result .motes() @@ -118,19 +117,16 @@ fn get_balance_should_work() { fn get_balance_using_public_key_should_work() { let protocol_version = ProtocolVersion::V2_0_0; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - TRANSFER_ARG_TARGET => *ALICE_ADDR, - TRANSFER_ARG_AMOUNT => *TRANSFER_AMOUNT_1, - TRANSFER_ARG_ID => >::None, - }, - ) - .build(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let block_time = 1_000_000; + let transfer_request = TransferRequestBuilder::new(*TRANSFER_AMOUNT_1, *ALICE_ADDR) + .with_block_time(block_time) + .build(); - builder.exec(transfer_request).commit().expect_success(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let alice_account = builder .get_entity_by_account_hash(*ALICE_ADDR) @@ -139,7 +135,7 @@ fn get_balance_using_public_key_should_work() { let alice_main_purse = alice_account.main_purse(); let alice_balance_result = - builder.get_public_key_balance_result(protocol_version, ALICE_KEY.clone()); + builder.get_public_key_balance_result(protocol_version, ALICE_KEY.clone(), block_time); let alice_balance = alice_balance_result .motes() diff --git a/execution_engine_testing/tests/src/test/groups.rs b/execution_engine_testing/tests/src/test/groups.rs index d6d112cb4e..04654fb9b7 100644 --- a/execution_engine_testing/tests/src/test/groups.rs +++ b/execution_engine_testing/tests/src/test/groups.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use assert_matches::assert_matches; use once_cell::sync::Lazy; @@ -7,7 +9,7 @@ use casper_engine_test_support::{ MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; -use casper_types::{account::AccountHash, runtime_args, Key, ProtocolVersion, RuntimeArgs, U512}; +use casper_types::{account::AccountHash, runtime_args, Key, RuntimeArgs, U512}; use crate::{lmdb_fixture, wasm_utils}; @@ -136,23 +138,21 @@ fn should_not_call_restricted_session_from_wrong_account() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_3 = { - let args = runtime_args! {}; - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_stored_versioned_contract_by_hash( - package_hash.into_package_addr().expect("should be hash"), - None, - RESTRICTED_SESSION, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let args = runtime_args! {}; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_stored_versioned_contract_by_hash( + package_hash.into_package_addr().expect("should be hash"), + None, + RESTRICTED_SESSION, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).commit(); @@ -166,9 +166,7 @@ fn should_not_call_restricted_session_from_wrong_account() { let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); } @@ -199,25 +197,23 @@ fn should_not_call_restricted_session_caller_from_wrong_account() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_3 = { - let args = runtime_args! { - "package_hash" => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_stored_versioned_contract_by_hash( - package_hash.into_package_addr().expect("should be hash"), - None, - RESTRICTED_SESSION_CALLER, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + "package_hash" => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_stored_versioned_contract_by_hash( + package_hash.into_package_addr().expect("should be hash"), + None, + RESTRICTED_SESSION_CALLER, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).commit(); @@ -231,9 +227,7 @@ fn should_not_call_restricted_session_caller_from_wrong_account() { let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); } @@ -244,7 +238,7 @@ fn should_call_group_restricted_contract() { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_new_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_new_protocol_version(DEFAULT_PROTOCOL_VERSION) .build() }; @@ -263,28 +257,21 @@ fn should_call_group_restricted_contract() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_2 = { - // This inserts package as an argument because this test - // can work from different accounts which might not have the same keys in their session - // code. - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - RESTRICTED_CONTRACT, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + // This inserts package as an argument because this test + // can work from different accounts which might not have the same keys in their session + // code. + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name(PACKAGE_HASH_KEY, None, RESTRICTED_CONTRACT, args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_2).expect_success().commit(); @@ -322,37 +309,33 @@ fn should_not_call_group_restricted_contract_from_wrong_account() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_3 = { - // This inserts package as an argument because this test - // can work from different accounts which might not have the same keys in their session - // code. - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_stored_versioned_contract_by_hash( - package_hash.into_package_addr().expect("should be hash"), - None, - RESTRICTED_CONTRACT, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + // This inserts package as an argument because this test + // can work from different accounts which might not have the same keys in their session + // code. + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_stored_versioned_contract_by_hash( + package_hash.into_package_addr().expect("should be hash"), + None, + RESTRICTED_CONTRACT, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).commit(); let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); } @@ -374,28 +357,23 @@ fn should_call_group_unrestricted_contract_caller() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_2 = { - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - UNRESTRICTED_CONTRACT_CALLER, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new() - .with_protocol_version(ProtocolVersion::V1_0_0) - .push_deploy(deploy) - .build() + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + PACKAGE_HASH_KEY, + None, + UNRESTRICTED_CONTRACT_CALLER, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_2).expect_success().commit(); let _account = builder @@ -416,7 +394,6 @@ fn should_call_unrestricted_contract_caller_from_different_account() { CONTRACT_TRANSFER_TO_ACCOUNT, runtime_args! { ARG_TARGET => ACCOUNT_1_ADDR, ARG_AMOUNT => *TRANSFER_1_AMOUNT }, ) - .with_protocol_version(ProtocolVersion::V1_0_0) .build(); builder.exec(exec_request_1).expect_success().commit(); @@ -444,7 +421,6 @@ fn should_call_unrestricted_contract_caller_from_different_account() { PACKAGE_HASH_ARG => *package_hash, }, ) - .with_protocol_version(ProtocolVersion::V1_0_0) .build(); builder.exec(exec_request_2).expect_success().commit(); @@ -544,9 +520,7 @@ fn should_call_group_restricted_contract_as_session_from_wrong_account() { let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); } @@ -568,57 +542,46 @@ fn should_not_call_uncallable_contract_from_deploy() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_2 = { - // This inserts package as an argument because this test - // can work from different accounts which might not have the same keys in their session - // code. - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - UNCALLABLE_SESSION, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + // This inserts package as an argument because this test + // can work from different accounts which might not have the same keys in their session + // code. + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name(PACKAGE_HASH_KEY, None, UNCALLABLE_SESSION, args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_2).commit(); let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); - let exec_request_3 = { - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - CALL_RESTRICTED_ENTRY_POINTS, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([6; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + PACKAGE_HASH_KEY, + None, + CALL_RESTRICTED_ENTRY_POINTS, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([6; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).expect_failure(); @@ -643,64 +606,54 @@ fn should_not_call_uncallable_session_from_deploy() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_2 = { - // This inserts package as an argument because this test - // can work from different accounts which might not have the same keys in their session - // code. - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - UNCALLABLE_CONTRACT, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + // This inserts package as an argument because this test + // can work from different accounts which might not have the same keys in their session + // code. + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name(PACKAGE_HASH_KEY, None, UNCALLABLE_CONTRACT, args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_2).commit(); let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); - let exec_request_3 = { - let args = runtime_args! { - PACKAGE_HASH_ARG => *package_hash, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - PACKAGE_HASH_KEY, - None, - CALL_RESTRICTED_ENTRY_POINTS, - args, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([6; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + PACKAGE_HASH_ARG => *package_hash, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + PACKAGE_HASH_KEY, + None, + CALL_RESTRICTED_ENTRY_POINTS, + args, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([6; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).expect_failure(); builder.assert_error(Error::Exec(ExecError::InvalidContext)) } -#[test] #[ignore] +#[allow(unused)] +// #[test] fn should_not_call_group_restricted_stored_payment_code_from_invalid_account() { // This test calls a stored payment code that is restricted with a group access using an account // that does not have any of the group urefs in context. @@ -728,27 +681,25 @@ fn should_not_call_group_restricted_stored_payment_code_from_invalid_account() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_3 = { - let args = runtime_args! { - "amount" => *DEFAULT_PAYMENT, - }; - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_stored_versioned_payment_contract_by_hash( - package_hash - .into_package_addr() - .expect("must have created package hash"), - None, - "restricted_standard_payment", - args, - ) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + "amount" => *DEFAULT_PAYMENT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_stored_versioned_payment_contract_by_hash( + package_hash + .into_package_addr() + .expect("must have created package hash"), + None, + "restricted_standard_payment", + args, + ) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).commit(); @@ -762,14 +713,13 @@ fn should_not_call_group_restricted_stored_payment_code_from_invalid_account() { let response = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let error = exec_response.as_error().expect("should have error"); + let error = response.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::InvalidContext)); } -#[test] #[ignore] +#[allow(unused)] +// #[test] fn should_call_group_restricted_stored_payment_code() { // This test calls a stored payment code that is restricted with a group access using an account // that contains urefs from the group. @@ -798,28 +748,26 @@ fn should_call_group_restricted_stored_payment_code() { .get(PACKAGE_ACCESS_KEY) .expect("should have package hash"); - let exec_request_3 = { - let args = runtime_args! { - "amount" => *DEFAULT_PAYMENT, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - // .with_stored_versioned_contract_by_name(name, version, entry_point, args) - .with_stored_versioned_payment_contract_by_hash( - package_hash - .into_package_addr() - .expect("must have created package hash"), - None, - "restricted_standard_payment", - args, - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([3; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + "amount" => *DEFAULT_PAYMENT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + // .with_stored_versioned_contract_by_name(name, version, entry_point, args) + .with_stored_versioned_payment_contract_by_hash( + package_hash + .into_package_addr() + .expect("must have created package hash"), + None, + "restricted_standard_payment", + args, + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([3; 32]) + .build(); + + let exec_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_3).expect_failure(); diff --git a/execution_engine_testing/tests/src/test/host_function_costs.rs b/execution_engine_testing/tests/src/test/host_function_costs.rs index 91065fb4c7..227859624e 100644 --- a/execution_engine_testing/tests/src/test/host_function_costs.rs +++ b/execution_engine_testing/tests/src/test/host_function_costs.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{bytesrepr::Bytes, runtime_args, AddressableEntityHash, RuntimeArgs}; @@ -30,7 +29,7 @@ fn should_measure_gas_cost() { .build(); // Create Accounts - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -98,7 +97,7 @@ fn should_measure_nested_host_function_call_cost() { .build(); // Create Accounts - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -176,7 +175,7 @@ fn should_measure_argument_size_in_host_function_call() { .build(); // Create Accounts - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/mod.rs b/execution_engine_testing/tests/src/test/mod.rs index d30b47c94f..fca009baed 100644 --- a/execution_engine_testing/tests/src/test/mod.rs +++ b/execution_engine_testing/tests/src/test/mod.rs @@ -1,4 +1,3 @@ -mod bulk_update_with_scratch_trie; mod chainspec_registry; mod check_transfer_success; mod contract_api; diff --git a/execution_engine_testing/tests/src/test/private_chain.rs b/execution_engine_testing/tests/src/test/private_chain.rs index 22b783f68d..a3c6963e92 100644 --- a/execution_engine_testing/tests/src/test/private_chain.rs +++ b/execution_engine_testing/tests/src/test/private_chain.rs @@ -97,17 +97,14 @@ static PRIVATE_CHAIN_GENESIS_VALIDATORS: Lazy> = Lazy::new(|| { let mut default_accounts = Vec::new(); - let proposer_account = GenesisAccount::account( - DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - Motes::new(U512::zero()), - None, - ); + let proposer_account = + GenesisAccount::account(DEFAULT_PROPOSER_PUBLIC_KEY.clone(), Motes::zero(), None); default_accounts.push(proposer_account); // One normal account that starts at genesis default_accounts.push(GenesisAccount::account( ACCOUNT_1_PUBLIC_KEY.clone(), - Motes::new(U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, )); @@ -119,7 +116,7 @@ static PRIVATE_CHAIN_DEFAULT_ACCOUNTS: Lazy> = Lazy::new(|| public_key, // Genesis validators for a private network doesn't have balances, but they are part of // fixed set of validators - balance: Motes::new(U512::zero()), + balance: Motes::zero(), validator: Some(genesis_validator), }); } @@ -148,15 +145,13 @@ static DEFUALT_PRIVATE_CHAIN_EXEC_CONFIG: Lazy = Lazy::new(|| { .with_round_seigniorage_rate(DEFAULT_ROUND_SEIGNIORAGE_RATE) .with_unbonding_delay(DEFAULT_UNBONDING_DELAY) .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) - .with_refund_handling(PRIVATE_CHAIN_REFUND_HANDLING) - .with_fee_handling(PRIVATE_CHAIN_FEE_HANDLING) .build() }); static DEFAULT_PRIVATE_CHAIN_GENESIS: Lazy = Lazy::new(|| { GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, DEFUALT_PRIVATE_CHAIN_EXEC_CONFIG.clone(), DEFAULT_CHAINSPEC_REGISTRY.clone(), ) diff --git a/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs b/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs index 921c92d646..95cb758ab4 100644 --- a/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs +++ b/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs @@ -1,24 +1,22 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, + TransferRequestBuilder, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{ - runtime_args, - system::{handle_payment::ACCUMULATION_PURSE_KEY, mint}, - EntityAddr, FeeHandling, MintCosts, RefundHandling, RuntimeArgs, DEFAULT_NOP_COST, U512, + system::handle_payment::ACCUMULATION_PURSE_KEY, EntityAddr, FeeHandling, MintCosts, + RefundHandling, DEFAULT_NOP_COST, U512, }; use num_rational::Ratio; use num_traits::{One, Zero}; -use crate::{ - test::private_chain::{ - self, ACCOUNT_1_ADDR, DEFAULT_ADMIN_ACCOUNT_ADDR, PRIVATE_CHAIN_ALLOW_AUCTION_BIDS, - PRIVATE_CHAIN_ALLOW_UNRESTRICTED_TRANSFERS, PRIVATE_CHAIN_COMPUTE_REWARDS, - }, - wasm_utils, +use crate::test::private_chain::{ + self, ACCOUNT_1_ADDR, DEFAULT_ADMIN_ACCOUNT_ADDR, PRIVATE_CHAIN_ALLOW_AUCTION_BIDS, + PRIVATE_CHAIN_ALLOW_UNRESTRICTED_TRANSFERS, PRIVATE_CHAIN_COMPUTE_REWARDS, }; #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_the_fees_without_refund() { let zero_refund_handling = RefundHandling::Refund { refund_ratio: Ratio::zero(), @@ -29,7 +27,8 @@ fn should_burn_the_fees_without_refund() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_the_fees_with_half_of_refund() { let half_refund_handling = RefundHandling::Refund { refund_ratio: Ratio::new(1, 2), @@ -41,7 +40,8 @@ fn should_burn_the_fees_with_half_of_refund() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_the_fees_with_refund() { let full_refund_handling = RefundHandling::Refund { refund_ratio: Ratio::one(), @@ -52,7 +52,8 @@ fn should_burn_the_fees_with_refund() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_full_refund_with_accumulating_fee() { let full_refund_handling = RefundHandling::Burn { refund_ratio: Ratio::one(), @@ -63,7 +64,8 @@ fn should_burn_full_refund_with_accumulating_fee() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_zero_refund_with_accumulating_fee() { let full_refund_handling = RefundHandling::Burn { refund_ratio: Ratio::zero(), @@ -74,7 +76,8 @@ fn should_burn_zero_refund_with_accumulating_fee() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_zero_refund_and_burn_fees() { let full_refund_handling = RefundHandling::Burn { refund_ratio: Ratio::zero(), @@ -83,8 +86,10 @@ fn should_burn_zero_refund_and_burn_fees() { let expected_fee_amount = *DEFAULT_PAYMENT; // 0% refund + fee test_burning_fees(full_refund_handling, fee_handling, expected_fee_amount); } + #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_burn_full_refund_and_burn_fees() { let full_refund_handling = RefundHandling::Burn { refund_ratio: Ratio::one(), @@ -106,6 +111,9 @@ fn test_burning_fees( fee_handling, PRIVATE_CHAIN_COMPUTE_REWARDS, ); + + let protocol_version = DEFAULT_PROTOCOL_VERSION; + let handle_payment = builder.get_handle_payment_contract_hash(); let handle_payment_1 = builder.get_named_keys(EntityAddr::System(handle_payment.value())); let rewards_purse_key = handle_payment_1 @@ -113,43 +121,42 @@ fn test_burning_fees( .expect("should have rewards purse"); let rewards_purse_uref = rewards_purse_key.into_uref().expect("should be uref"); assert_eq!(builder.get_purse_balance(rewards_purse_uref), U512::zero()); - let exec_request_1 = ExecuteRequestBuilder::module_bytes( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - wasm_utils::do_minimum_bytes(), - RuntimeArgs::default(), - ) - .build(); - let total_supply_before = builder.total_supply(None); - let exec_request_1_proposer = exec_request_1.proposer.clone(); - let proposer_account_1 = builder - .get_entity_by_account_hash(exec_request_1_proposer.to_account_hash()) - .expect("should have proposer account"); - builder.exec(exec_request_1).expect_success().commit(); - assert_eq!( - builder.get_purse_balance(proposer_account_1.main_purse()), - U512::zero(), - "proposer should not receive anything", - ); - let total_supply_after = builder.total_supply(None); + let total_supply_before = builder.total_supply(None, protocol_version); + // TODO: reevaluate this test, considering fee / refund / pricing modes + // let exec_request_1 = ExecuteRequestBuilder::module_bytes( + // *DEFAULT_ADMIN_ACCOUNT_ADDR, + // wasm_utils::do_minimum_bytes(), + // RuntimeArgs::default(), + // ) + // .build(); + // let exec_request_1_proposer = exec_request_1.proposer.clone(); + // let proposer_account_1 = builder + // .get_entity_by_account_hash(exec_request_1_proposer.to_account_hash()) + // .expect("should have proposer account"); + // builder.exec(exec_request_1).expect_success().commit(); + // assert_eq!( + // builder.get_purse_balance(proposer_account_1.main_purse()), + // U512::zero(), + // "proposer should not receive anything", + // ); + let total_supply_after = builder.total_supply(None, protocol_version); assert_eq!( total_supply_before - total_supply_after, expected_burn_amount, "total supply should be burned exactly by the amount of calculated fee after refund" ); - let exec_request_2 = { - let transfer_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }; - ExecuteRequestBuilder::transfer(*DEFAULT_ADMIN_ACCOUNT_ADDR, transfer_args).build() - }; - let total_supply_before = builder.total_supply(None); - builder.exec(exec_request_2).expect_success().commit(); - let total_supply_after = builder.total_supply(None); + let transfer_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); + let total_supply_before = builder.total_supply(None, protocol_version); + builder + .transfer_and_commit(transfer_request) + .expect_success(); + let total_supply_after = builder.total_supply(None, protocol_version); match fee_handling { - FeeHandling::PayToProposer | FeeHandling::Accumulate | FeeHandling::None => { + FeeHandling::PayToProposer | FeeHandling::Accumulate | FeeHandling::NoFee => { assert_eq!(total_supply_before, total_supply_after); } FeeHandling::Burn => { diff --git a/execution_engine_testing/tests/src/test/private_chain/fees_accumulation.rs b/execution_engine_testing/tests/src/test/private_chain/fees_accumulation.rs index add67b366b..9a6dee61ad 100644 --- a/execution_engine_testing/tests/src/test/private_chain/fees_accumulation.rs +++ b/execution_engine_testing/tests/src/test/private_chain/fees_accumulation.rs @@ -1,16 +1,14 @@ +use std::collections::BTreeSet; + use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_BLOCK_TIME, DEFAULT_PROPOSER_ADDR, DEFAULT_PROTOCOL_VERSION, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, UpgradeRequestBuilder, + DEFAULT_ACCOUNT_ADDR, DEFAULT_BLOCK_TIME, DEFAULT_PROPOSER_ADDR, DEFAULT_PROTOCOL_VERSION, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{ - account::AccountHash, - runtime_args, - system::{handle_payment::ACCUMULATION_PURSE_KEY, mint}, - EntityAddr, EraId, FeeHandling, Key, ProtocolVersion, RuntimeArgs, U512, + account::AccountHash, system::handle_payment::ACCUMULATION_PURSE_KEY, EntityAddr, EraId, + FeeHandling, Key, ProtocolVersion, RuntimeArgs, U512, }; -use once_cell::sync::Lazy; -use std::collections::BTreeSet; use crate::{ lmdb_fixture, @@ -18,20 +16,18 @@ use crate::{ wasm_utils, }; -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); #[ignore] #[test] fn default_genesis_config_should_not_have_rewards_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let handle_payment = builder.get_handle_payment_contract_hash(); let handle_payment_contract = @@ -65,15 +61,15 @@ fn should_finalize_and_accumulate_rewards_purse() { ) .build(); - let exec_request_1_proposer = exec_request_1.proposer.clone(); - let proposer_account_1 = builder - .get_entity_with_named_keys_by_account_hash(exec_request_1_proposer.to_account_hash()) - .expect("should have proposer account"); + // let exec_request_1_proposer = exec_request_1.proposer.clone(); + // let proposer_account_1 = builder + // .get_entity_with_named_keys_by_account_hash(exec_request_1_proposer.to_account_hash()) + // .expect("should have proposer account"); builder.exec(exec_request_1).expect_success().commit(); - assert_eq!( - builder.get_purse_balance(proposer_account_1.main_purse()), - U512::zero() - ); + // assert_eq!( + // builder.get_purse_balance(proposer_account_1.main_purse()), + // U512::zero() + // ); let handle_payment_2 = builder.get_named_keys(EntityAddr::System(handle_payment.value())); @@ -82,40 +78,40 @@ fn should_finalize_and_accumulate_rewards_purse() { "none of the named keys should change before and after execution" ); - let exec_request_2 = { - let transfer_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }; - ExecuteRequestBuilder::transfer(*DEFAULT_ADMIN_ACCOUNT_ADDR, transfer_args).build() - }; - - let exec_request_2_proposer = exec_request_2.proposer.clone(); - let proposer_account_2 = builder - .get_entity_by_account_hash(exec_request_2_proposer.to_account_hash()) - .expect("should have proposer account"); - - builder.exec(exec_request_2).expect_success().commit(); - assert_eq!( - builder.get_purse_balance(proposer_account_2.main_purse()), - U512::zero() - ); - - let handle_payment_3 = builder.get_named_keys(EntityAddr::System(handle_payment.value())); - - assert_eq!( - handle_payment_1, handle_payment_2, - "none of the named keys should change before and after execution" - ); - assert_eq!( - handle_payment_2, handle_payment_3, - "none of the named keys should change before and after execution" - ); + let _transfer_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); + + // TODO - re-enable once payment epic completed. + // let exec_request_2_proposer = transfer_request.proposer().clone(); + // let proposer_account_2 = builder + // .get_entity_by_account_hash(exec_request_2_proposer.to_account_hash()) + // .expect("should have proposer account"); + // + // builder + // .transfer_and_commit(transfer_request) + // .expect_success(); + // assert_eq!( + // builder.get_purse_balance(proposer_account_2.main_purse()), + // U512::zero() + // ); + // + // let handle_payment_3 = builder.get_named_keys(EntityAddr::System(handle_payment.value())); + // + // assert_eq!( + // handle_payment_1, handle_payment_2, + // "none of the named keys should change before and after execution" + // ); + // assert_eq!( + // handle_payment_2, handle_payment_3, + // "none of the named keys should change before and after execution" + // ); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_accumulate_deploy_fees() { let mut builder = super::private_chain_setup(); @@ -141,7 +137,7 @@ fn should_accumulate_deploy_fees() { ) .build(); - let exec_request_proposer = exec_request.proposer.clone(); + // let exec_request_proposer = exec_request.proposer.clone(); builder.exec(exec_request).expect_success().commit(); @@ -165,19 +161,20 @@ fn should_accumulate_deploy_fees() { "rewards balance should increase" ); - // Ensures default proposer didn't receive any funds - let proposer_account = builder - .get_entity_by_account_hash(exec_request_proposer.to_account_hash()) - .expect("should have proposer account"); - - assert_eq!( - builder.get_purse_balance(proposer_account.main_purse()), - U512::zero() - ); + // // Ensures default proposer didn't receive any funds + // let proposer_account = builder + // .get_entity_by_account_hash(exec_request_proposer.to_account_hash()) + // .expect("should have proposer account"); + // + // assert_eq!( + // builder.get_purse_balance(proposer_account.main_purse()), + // U512::zero() + // ); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_distribute_accumulated_fees_to_admins() { let mut builder = super::private_chain_setup(); @@ -215,7 +212,7 @@ fn should_distribute_accumulated_fees_to_admins() { let mut administrative_accounts: BTreeSet = BTreeSet::new(); administrative_accounts.insert(*DEFAULT_ADMIN_ACCOUNT_ADDR); - let result = builder.distribute_fees(None, *DEFAULT_PROTOCOL_VERSION, DEFAULT_BLOCK_TIME); + let result = builder.distribute_fees(None, DEFAULT_PROTOCOL_VERSION, DEFAULT_BLOCK_TIME); assert!(result.is_success(), "expected success not: {:?}", result); @@ -237,7 +234,8 @@ fn should_distribute_accumulated_fees_to_admins() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_accumulate_fees_after_upgrade() { let (mut builder, _lmdb_fixture_state, _temp_dir) = lmdb_fixture::builder_from_global_state_fixture(lmdb_fixture::RELEASE_1_4_5); @@ -270,8 +268,8 @@ fn should_accumulate_fees_after_upgrade() { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(EraId::default()) .with_fee_handling(FeeHandling::Accumulate) .build() diff --git a/execution_engine_testing/tests/src/test/private_chain/management.rs b/execution_engine_testing/tests/src/test/private_chain/management.rs index bca9b6484d..65ffa72d8b 100644 --- a/execution_engine_testing/tests/src/test/private_chain/management.rs +++ b/execution_engine_testing/tests/src/test/private_chain/management.rs @@ -1,16 +1,14 @@ use std::convert::TryFrom; use casper_engine_test_support::{ - ChainspecConfig, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, - DEFAULT_AUCTION_DELAY, DEFAULT_CHAINSPEC_REGISTRY, DEFAULT_GENESIS_CONFIG_HASH, - DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PAYMENT, - DEFAULT_PROTOCOL_VERSION, DEFAULT_ROUND_SEIGNIORAGE_RATE, DEFAULT_SYSTEM_CONFIG, - DEFAULT_UNBONDING_DELAY, DEFAULT_VALIDATOR_SLOTS, DEFAULT_WASM_CONFIG, -}; -use casper_execution_engine::{ - engine_state::{Error, ExecuteRequest}, - execution::ExecError, + ChainspecConfig, DeployItemBuilder, ExecuteRequest, ExecuteRequestBuilder, LmdbWasmTestBuilder, + TransferRequestBuilder, DEFAULT_AUCTION_DELAY, DEFAULT_CHAINSPEC_REGISTRY, + DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_GENESIS_TIMESTAMP_MILLIS, + DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, + DEFAULT_ROUND_SEIGNIORAGE_RATE, DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY, + DEFAULT_VALIDATOR_SLOTS, DEFAULT_WASM_CONFIG, }; +use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_storage::{data_access_layer::GenesisRequest, tracking_copy::TrackingCopyError}; use casper_types::{ account::{AccountHash, Weight}, @@ -104,13 +102,11 @@ fn should_not_run_genesis_with_duplicated_administrator_accounts() { .with_round_seigniorage_rate(DEFAULT_ROUND_SEIGNIORAGE_RATE) .with_unbonding_delay(DEFAULT_UNBONDING_DELAY) .with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS) - .with_refund_handling(PRIVATE_CHAIN_REFUND_HANDLING) - .with_fee_handling(PRIVATE_CHAIN_FEE_HANDLING) .build(); let modified_genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -230,27 +226,25 @@ fn genesis_accounts_should_not_remove_associated_keys() { let mut builder = super::private_chain_setup(); - let add_associated_key_request = { - let session_args = runtime_args! { - ARG_ACCOUNT => secondary_account_hash, - ARG_WEIGHT => Weight::MAX, - }; - - let account_hash = *ACCOUNT_1_ADDR; - let deploy_hash: [u8; 32] = [55; 32]; + let session_args = runtime_args! { + ARG_ACCOUNT => secondary_account_hash, + ARG_WEIGHT => Weight::MAX, + }; - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(ADD_ASSOCIATED_KEY_CONTRACT, session_args) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*ADMIN_1_ACCOUNT_ADDR]) - .with_deploy_hash(deploy_hash) - .build(); + let account_hash = *ACCOUNT_1_ADDR; + let deploy_hash: [u8; 32] = [55; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(ADD_ASSOCIATED_KEY_CONTRACT, session_args) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }) + .with_authorization_keys(&[*ADMIN_1_ACCOUNT_ADDR]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let add_associated_key_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(add_associated_key_request) @@ -304,29 +298,25 @@ fn administrator_account_should_disable_any_account() { builder.exec(exec_request_1).expect_success().commit(); // Disable account 1 - let disable_request_1 = { - let session_args = runtime_args! { - ARG_DEPLOY_THRESHOLD => Weight::MAX, - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::MAX, - }; - - { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [54; 32]; - - // Here, deploy is sent as an account, but signed by an administrator. - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - } + let session_args = runtime_args! { + ARG_DEPLOY_THRESHOLD => Weight::MAX, + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::MAX, }; + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [54; 32]; + + // Here, deploy is sent as an account, but signed by an administrator. + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) + .with_deploy_hash(deploy_hash) + .build(); + + let disable_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(disable_request_1).expect_success().commit(); // Account 1 can not deploy after freezing let exec_request_2 = ExecuteRequestBuilder::module_bytes( @@ -352,47 +342,43 @@ fn administrator_account_should_disable_any_account() { ); // Unfreeze account 1 - let enable_request_1 = { - let session_args = runtime_args! { - ARG_DEPLOY_THRESHOLD => Weight::new(1), - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), - }; + let session_args = runtime_args! { + ARG_DEPLOY_THRESHOLD => Weight::new(1), + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(0), + }; - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [53; 32]; + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [53; 32]; - // Here, deploy is sent as an account, but signed by an administrator. - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) - .with_deploy_hash(deploy_hash) - .build(); + // Here, deploy is sent as an account, but signed by an administrator. + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let enable_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - let enable_request_2 = { - let session_args = runtime_args! { - ARG_DEPLOY_THRESHOLD => Weight::new(0), - ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), - }; + let session_args = runtime_args! { + ARG_DEPLOY_THRESHOLD => Weight::new(0), + ARG_KEY_MANAGEMENT_THRESHOLD => Weight::new(1), + }; - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [52; 32]; + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [52; 32]; - // Here, deploy is sent as an account, but signed by an administrator. - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) - .with_deploy_hash(deploy_hash) - .build(); + // Here, deploy is sent as an account, but signed by an administrator. + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_code(SET_ACTION_THRESHOLDS_CONTRACT, session_args) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ADMIN_ACCOUNT_ADDR]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let enable_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(enable_request_1).expect_success().commit(); builder.exec(enable_request_2).expect_success().commit(); @@ -421,15 +407,13 @@ fn native_transfer_should_create_new_private_account() { let mut builder = super::private_chain_setup(); // Account 1 can deploy after genesis - let transfer_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => Some(1u64), - }; - let transfer_request = - ExecuteRequestBuilder::transfer(*DEFAULT_ADMIN_ACCOUNT_ADDR, transfer_args).build(); + let transfer_request = TransferRequestBuilder::new(1, *ACCOUNT_2_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); - builder.exec(transfer_request).expect_success().commit(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let _account_2 = builder .get_entity_by_account_hash(*ACCOUNT_2_ADDR) @@ -712,28 +696,22 @@ fn administrator_account_should_disable_any_contract_used_as_payment() { ); // Account 1 can deploy after genesis - let exec_request_1 = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let session_args = RuntimeArgs::default(); - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_stored_payment_named_key( - TEST_PAYMENT_STORED_HASH_NAME, - PAY_ENTRYPOINT, - payment_args, - ) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = RuntimeArgs::default(); + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_stored_payment_named_key(TEST_PAYMENT_STORED_HASH_NAME, PAY_ENTRYPOINT, payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_1).expect_failure(); @@ -763,48 +741,37 @@ fn administrator_account_should_disable_any_contract_used_as_payment() { ); assert!(!contract_package_after_disable.is_entity_enabled(&stored_entity_hash),); - let call_stored_payment_requests_1 = { - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let session_args = RuntimeArgs::default(); - - let call_by_name = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args.clone()) - .with_stored_payment_named_key( - TEST_PAYMENT_STORED_HASH_NAME, - PAY_ENTRYPOINT, - payment_args.clone(), - ) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - let call_by_hash = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_stored_payment_hash(stored_entity_hash, PAY_ENTRYPOINT, payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - vec![call_by_name, call_by_hash] + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = RuntimeArgs::default(); + + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args.clone()) + .with_stored_payment_named_key( + TEST_PAYMENT_STORED_HASH_NAME, + PAY_ENTRYPOINT, + payment_args.clone(), + ) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let call_by_name = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_stored_payment_hash(stored_entity_hash, PAY_ENTRYPOINT, payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let call_by_hash = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - for execute_request in call_stored_payment_requests_1 { + for execute_request in [call_by_name, call_by_hash] { builder.exec(execute_request).expect_failure().commit(); let error = builder.get_error().expect("should have error"); assert!( @@ -831,48 +798,33 @@ fn administrator_account_should_disable_any_contract_used_as_payment() { builder.exec(enable_request).expect_success().commit(); - let call_stored_payment_requests_2 = { - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let session_args = RuntimeArgs::default(); - - let call_by_name = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args.clone()) - .with_stored_payment_named_key( - TEST_PAYMENT_STORED_HASH_NAME, - PAY_ENTRYPOINT, - payment_args.clone(), - ) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - let call_by_hash = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_stored_payment_hash(stored_entity_hash, PAY_ENTRYPOINT, payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - vec![call_by_name, call_by_hash] - }; + let payment_args = runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }; + let session_args = RuntimeArgs::default(); + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args.clone()) + .with_stored_payment_named_key( + TEST_PAYMENT_STORED_HASH_NAME, + PAY_ENTRYPOINT, + payment_args.clone(), + ) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let call_by_name = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_stored_payment_hash(stored_entity_hash, PAY_ENTRYPOINT, payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let call_by_hash = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - for exec_request in call_stored_payment_requests_2 { + for exec_request in [call_by_name, call_by_hash] { builder.exec(exec_request).expect_failure(); } } diff --git a/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs b/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs index 0e522b6188..7173cf6eb5 100644 --- a/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs +++ b/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs @@ -17,19 +17,20 @@ fn should_not_distribute_rewards_but_compute_next_set() { let mut builder = super::private_chain_setup(); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); for _ in 0..3 { builder.distribute( None, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_PROTOCOL_VERSION, IntoIterator::into_iter([(VALIDATOR_1_PUBLIC_KEY.clone(), U512::from(0))]).collect(), DEFAULT_BLOCK_TIME, ); let step_request = StepRequestBuilder::new() .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_next_era_id(builder.get_era().successor()) .with_era_end_timestamp_millis(timestamp_millis) .with_run_auction(true) @@ -49,14 +50,14 @@ fn should_not_distribute_rewards_but_compute_next_set() { builder.distribute( None, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_PROTOCOL_VERSION, IntoIterator::into_iter([(VALIDATOR_1_PUBLIC_KEY.clone(), U512::from(0))]).collect(), DEFAULT_BLOCK_TIME, ); let step_request = StepRequestBuilder::new() .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_reward_item(RewardItem::new( VALIDATOR_1_PUBLIC_KEY.clone(), VALIDATOR_1_REWARD_FACTOR, @@ -100,7 +101,7 @@ fn should_not_distribute_rewards_but_compute_next_set() { era_info ); - let total_supply_after_distribution = builder.total_supply(None); + let total_supply_after_distribution = builder.total_supply(None, protocol_version); assert_eq!( initial_supply, total_supply_after_distribution, "total supply of tokens should not increase after an auction is ran" diff --git a/execution_engine_testing/tests/src/test/private_chain/unrestricted_transfers.rs b/execution_engine_testing/tests/src/test/private_chain/unrestricted_transfers.rs index 1d09183447..08f2296a53 100644 --- a/execution_engine_testing/tests/src/test/private_chain/unrestricted_transfers.rs +++ b/execution_engine_testing/tests/src/test/private_chain/unrestricted_transfers.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, - SYSTEM_ADDR, + DeployItemBuilder, ExecuteRequestBuilder, TransferRequestBuilder, DEFAULT_PAYMENT, + MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_storage::system::transfer::TransferError; @@ -30,31 +30,24 @@ const TEST_PAYMENT_STORED_HASH_NAME: &str = "test_payment_hash"; fn should_disallow_native_unrestricted_transfer_to_create_new_account_by_user() { let mut builder = super::private_chain_setup(); - let fund_transfer_1 = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_transfer_1 = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); // Admin can transfer funds to create new account. - builder.exec(fund_transfer_1).expect_success().commit(); + builder + .transfer_and_commit(fund_transfer_1) + .expect_success(); - let transfer_request_1 = ExecuteRequestBuilder::transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => >::None, - }, - ) - .build(); + let transfer_request_1 = TransferRequestBuilder::new(1, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); // User can't transfer funds to create new account. - builder.exec(transfer_request_1).expect_failure().commit(); + builder + .transfer_and_commit(transfer_request_1) + .expect_failure(); let error = builder.get_error().expect("should have error"); assert!( @@ -66,18 +59,14 @@ fn should_disallow_native_unrestricted_transfer_to_create_new_account_by_user() error ); - let transfer_request_2 = ExecuteRequestBuilder::transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - mint::ARG_TARGET => *DEFAULT_ADMIN_ACCOUNT_ADDR, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => >::None, - }, - ) - .build(); + let transfer_request_2 = TransferRequestBuilder::new(1, *DEFAULT_ADMIN_ACCOUNT_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); // User can transfer funds back to admin. - builder.exec(transfer_request_2).expect_success().commit(); + builder + .transfer_and_commit(transfer_request_2) + .expect_success(); } #[ignore] @@ -323,28 +312,22 @@ fn should_disallow_transfer_to_unknown_target_from_non_admin() { let account = builder .get_entity_with_named_keys_by_account_hash(*ACCOUNT_1_ADDR) .expect("should have account"); - let source: URef = account.main_purse(); - let target: URef = account + let source = account.main_purse(); + let target = account .named_keys() .get(TEST_PURSE) .unwrap() .into_uref() .expect("should be uref"); - let amount: U512 = U512::one(); - let id: Option = None; - let transfer_request = ExecuteRequestBuilder::transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - mint::ARG_SOURCE => source, - mint::ARG_TARGET => target, - mint::ARG_AMOUNT => amount, - mint::ARG_ID => id, - }, - ) - .build(); + let transfer_request = TransferRequestBuilder::new(1, target) + .with_initiator(*ACCOUNT_1_ADDR) + .with_source(source) + .build(); - builder.exec(transfer_request).expect_failure().commit(); + builder + .transfer_and_commit(transfer_request) + .expect_failure(); let error = builder.get_error().expect("should have error"); assert!( @@ -377,28 +360,22 @@ fn should_allow_admin_to_transfer_to_own_purse_via_native_transfer() { let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ADMIN_ACCOUNT_ADDR) .expect("should have account"); - let source: URef = account.main_purse(); - let target: URef = account + let source = account.main_purse(); + let target = account .named_keys() .get(TEST_PURSE) .unwrap() .into_uref() .expect("should be uref"); - let amount: U512 = U512::one(); - let id: Option = None; - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_SOURCE => source, - mint::ARG_TARGET => target, - mint::ARG_AMOUNT => amount, - mint::ARG_ID => id, - }, - ) - .build(); + let transfer_request = TransferRequestBuilder::new(1, target) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .with_source(source) + .build(); - builder.exec(transfer_request).expect_success().commit(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); } #[ignore] @@ -441,7 +418,8 @@ fn should_disallow_wasm_payment_to_purse() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_allow_payment_to_purse_in_stored_payment() { // This effectively disables any custom payment code let mut builder = super::private_chain_setup(); @@ -459,29 +437,23 @@ fn should_not_allow_payment_to_purse_in_stored_payment() { .commit(); // Account 1 can deploy after genesis - let exec_request_1 = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let session_args = RuntimeArgs::default(); - - const PAY_ENTRYPOINT: &str = "pay"; - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_stored_payment_named_key( - TEST_PAYMENT_STORED_HASH_NAME, - PAY_ENTRYPOINT, - payment_args, - ) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; + + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = RuntimeArgs::default(); + + const PAY_ENTRYPOINT: &str = "pay"; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_stored_payment_named_key(TEST_PAYMENT_STORED_HASH_NAME, PAY_ENTRYPOINT, payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_1).expect_failure().commit(); @@ -498,42 +470,32 @@ fn should_not_allow_payment_to_purse_in_stored_payment() { fn should_disallow_native_unrestricted_transfer_to_existing_account_by_user() { let mut builder = super::private_chain_setup(); - let fund_transfer_1 = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_transfer_1 = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); - let fund_transfer_2 = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_transfer_2 = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_2_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); // Admin can transfer funds to create new account. - builder.exec(fund_transfer_1).expect_success().commit(); - builder.exec(fund_transfer_2).expect_success().commit(); + builder + .transfer_and_commit(fund_transfer_1) + .expect_success(); + builder + .transfer_and_commit(fund_transfer_2) + .expect_success(); - let transfer_request_1 = ExecuteRequestBuilder::transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => >::None, - }, - ) - .build(); + let transfer_request_1 = TransferRequestBuilder::new(1, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); // User can't transfer funds to create new account. - builder.exec(transfer_request_1).expect_failure().commit(); + builder + .transfer_and_commit(transfer_request_1) + .expect_failure(); let error = builder.get_error().expect("should have error"); assert!( @@ -545,18 +507,14 @@ fn should_disallow_native_unrestricted_transfer_to_existing_account_by_user() { error ); - let transfer_request_2 = ExecuteRequestBuilder::transfer( - *ACCOUNT_1_ADDR, - runtime_args! { - mint::ARG_TARGET => *DEFAULT_ADMIN_ACCOUNT_ADDR, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => >::None, - }, - ) - .build(); + let transfer_request_2 = TransferRequestBuilder::new(1, *DEFAULT_ADMIN_ACCOUNT_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); // User can transfer funds back to admin. - builder.exec(transfer_request_2).expect_success().commit(); + builder + .transfer_and_commit(transfer_request_2) + .expect_success(); } #[ignore] @@ -574,19 +532,16 @@ fn should_disallow_wasm_unrestricted_transfer_to_existing_account_by_user() { ) .build(); - let fund_transfer_2 = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_transfer_2 = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_2_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); // Admin can transfer funds to create new account. builder.exec(fund_transfer_1).expect_success().commit(); - builder.exec(fund_transfer_2).expect_success().commit(); + builder + .transfer_and_commit(fund_transfer_2) + .expect_success(); let transfer_request_1 = ExecuteRequestBuilder::standard( *ACCOUNT_1_ADDR, @@ -709,31 +664,30 @@ fn should_not_allow_direct_mint_transfer_without_to_field() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_allow_custom_payment_by_paying_to_system_account() { let mut builder = super::private_chain_setup(); // Account 1 can deploy after genesis - let exec_request_1 = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let payment_amount = *DEFAULT_PAYMENT + U512::from(1u64); - - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => payment_amount, - }; - let session_args = RuntimeArgs::default(); - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_payment_code("non_standard_payment.wasm", payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; + + let payment_amount = *DEFAULT_PAYMENT + U512::from(1u64); + + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => payment_amount, }; + let session_args = RuntimeArgs::default(); + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_payment_code("non_standard_payment.wasm", payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request_1).expect_success().commit(); @@ -757,30 +711,28 @@ fn should_allow_wasm_transfer_to_system() { let mut builder = super::private_chain_setup(); // Account 1 can deploy after genesis - let exec_request_1 = { - let sender = *ACCOUNT_1_ADDR; - let deploy_hash = [100; 32]; - - let payment_amount = *DEFAULT_PAYMENT + U512::from(1u64); - - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => payment_amount, - }; - let session_args = runtime_args! { - "target" => *SYSTEM_ADDR, - "amount" => U512::one(), - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_session_code("transfer_to_account_u512.wasm", session_args) - .with_payment_bytes(Vec::new(), payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *ACCOUNT_1_ADDR; + let deploy_hash = [100; 32]; + + let payment_amount = *DEFAULT_PAYMENT + U512::from(1u64); + + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => payment_amount, + }; + let session_args = runtime_args! { + "target" => *SYSTEM_ADDR, + "amount" => U512::one(), }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_session_code("transfer_to_account_u512.wasm", session_args) + .with_payment_bytes(Vec::new(), payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + let exec_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(exec_request_1).expect_success().commit(); let handle_payment_contract = builder.get_named_keys(EntityAddr::System( @@ -818,17 +770,14 @@ fn should_allow_transfer_to_system_in_a_native_transfer() { "payment purse should be empty" ); - let fund_transfer_1 = ExecuteRequestBuilder::transfer( - *DEFAULT_ADMIN_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => *SYSTEM_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_transfer_1 = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *SYSTEM_ADDR) + .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) + .build(); - builder.exec(fund_transfer_1).expect_success().commit(); + builder + .transfer_and_commit(fund_transfer_1) + .expect_success(); assert_eq!( builder.get_purse_balance(payment_purse_uref), diff --git a/execution_engine_testing/tests/src/test/regression/ee_1045.rs b/execution_engine_testing/tests/src/test/regression/ee_1045.rs index 6078d123e2..310f6d0e5e 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1045.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1045.rs @@ -52,33 +52,33 @@ const ACCOUNT_4_BOND: u64 = 200_000; fn should_run_ee_1045_squash_validators() { let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let account_3 = GenesisAccount::account( ACCOUNT_3_PK.clone(), - Motes::new(ACCOUNT_3_BALANCE.into()), + Motes::new(ACCOUNT_3_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_3_BOND.into()), + Motes::new(ACCOUNT_3_BOND), DelegationRate::zero(), )), ); let account_4 = GenesisAccount::account( ACCOUNT_4_PK.clone(), - Motes::new(ACCOUNT_4_BALANCE.into()), + Motes::new(ACCOUNT_4_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_4_BOND.into()), + Motes::new(ACCOUNT_4_BOND), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1071.rs b/execution_engine_testing/tests/src/test/regression/ee_1071.rs index 5b18f35937..5981580cd7 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1071.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1071.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{EntityAddr, RuntimeArgs}; @@ -20,7 +19,7 @@ fn should_run_ee_1071_regression() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1119.rs b/execution_engine_testing/tests/src/test/regression/ee_1119.rs index 78bd0a7665..ef1fdaee6f 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1119.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1119.rs @@ -48,9 +48,9 @@ fn should_slash_validator_and_their_delegators() { let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1120.rs b/execution_engine_testing/tests/src/test/regression/ee_1120.rs index 3d520f9d08..9447e0a121 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1120.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1120.rs @@ -59,17 +59,17 @@ fn should_run_ee_1120_slash_delegators() { let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let validator_2 = GenesisAccount::account( VALIDATOR_2.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_2_STAKE.into()), + Motes::new(VALIDATOR_2_STAKE), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1129.rs b/execution_engine_testing/tests/src/test/regression/ee_1129.rs index 96312c12ba..3d9e3ecf62 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1129.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1129.rs @@ -2,12 +2,12 @@ use casper_wasm::builder; use num_traits::Zero; use once_cell::sync::Lazy; -use casper_types::{GenesisAccount, GenesisValidator}; +use casper_types::{GenesisAccount, GenesisValidator, Key}; use casper_engine_test_support::{ utils, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_ACCOUNT_PUBLIC_KEY, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{ engine_state::Error, execution::ExecError, runtime::PreprocessingError, @@ -17,7 +17,7 @@ use casper_types::{ addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, system::auction::{self, DelegationRate}, - Motes, PublicKey, RuntimeArgs, SecretKey, DEFAULT_ADD_BID_COST, DEFAULT_DELEGATE_COST, U512, + Motes, PublicKey, RuntimeArgs, SecretKey, DEFAULT_DELEGATE_COST, U512, }; use crate::wasm_utils; @@ -35,22 +35,22 @@ static VALIDATOR_1: Lazy = Lazy::new(|| { }); static VALIDATOR_1_ADDR: Lazy = Lazy::new(|| AccountHash::from(&*VALIDATOR_1)); const VALIDATOR_1_STAKE: u64 = 250_000; -static UNDERFUNDED_DELEGATE_AMOUNT: Lazy = - Lazy::new(|| U512::from(DEFAULT_DELEGATE_COST - 1)); -static UNDERFUNDED_ADD_BID_AMOUNT: Lazy = Lazy::new(|| U512::from(DEFAULT_ADD_BID_COST - 1)); +static UNDERFUNDED_DELEGATE_AMOUNT: Lazy = Lazy::new(|| U512::from(1)); +static UNDERFUNDED_ADD_BID_AMOUNT: Lazy = Lazy::new(|| U512::from(1)); static CALL_STORED_CONTRACT_OVERHEAD: Lazy = Lazy::new(|| U512::from(10_001)); #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_ee_1129_underfunded_delegate_call() { assert!(U512::from(DEFAULT_DELEGATE_COST) > *UNDERFUNDED_DELEGATE_AMOUNT); let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); @@ -67,7 +67,7 @@ fn should_run_ee_1129_underfunded_delegate_call() { let auction = builder.get_auction_contract_hash(); - let bid_amount = U512::one(); + let bid_amount = U512::from(100_000_000_000_000u64); let deploy_hash = [42; 32]; @@ -77,26 +77,24 @@ fn should_run_ee_1129_underfunded_delegate_call() { auction::ARG_AMOUNT => bid_amount, }; - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_stored_session_hash(auction, auction::METHOD_DELEGATE, args) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *UNDERFUNDED_DELEGATE_AMOUNT, // underfunded deploy }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash(deploy_hash) .build(); - let exec_request = ExecuteRequestBuilder::new().push_deploy(deploy).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit(); let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); @@ -108,14 +106,13 @@ fn should_run_ee_1129_underfunded_delegate_call() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_ee_1129_underfunded_add_bid_call() { - assert!(U512::from(DEFAULT_ADD_BID_COST) > *UNDERFUNDED_ADD_BID_AMOUNT); - let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ); @@ -141,26 +138,24 @@ fn should_run_ee_1129_underfunded_add_bid_call() { auction::ARG_DELEGATION_RATE => delegation_rate, }; - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*VALIDATOR_1_ADDR) .with_stored_session_hash(auction, auction::METHOD_ADD_BID, args) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *UNDERFUNDED_DELEGATE_AMOUNT, }) .with_authorization_keys(&[*VALIDATOR_1_ADDR]) .with_deploy_hash(deploy_hash) .build(); - let exec_request = ExecuteRequestBuilder::new().push_deploy(deploy).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit(); let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); @@ -172,11 +167,12 @@ fn should_run_ee_1129_underfunded_add_bid_call() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_ee_1129_underfunded_mint_contract_call() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -185,19 +181,17 @@ fn should_run_ee_1129_underfunded_mint_contract_call() { ) .build(); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_session_named_key(CONTRACT_KEY, ENTRY_POINT_NAME, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_session_named_key(CONTRACT_KEY, ENTRY_POINT_NAME, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(install_exec_request).expect_success().commit(); @@ -206,9 +200,7 @@ fn should_run_ee_1129_underfunded_mint_contract_call() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); @@ -224,7 +216,7 @@ fn should_run_ee_1129_underfunded_mint_contract_call() { fn should_not_panic_when_calling_session_contract_by_uref() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -233,19 +225,17 @@ fn should_not_panic_when_calling_session_contract_by_uref() { ) .build(); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_session_named_key(ACCESS_KEY, ENTRY_POINT_NAME, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_session_named_key(ACCESS_KEY, ENTRY_POINT_NAME, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(install_exec_request).expect_success().commit(); @@ -254,14 +244,12 @@ fn should_not_panic_when_calling_session_contract_by_uref() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); assert!( - matches!(error, Error::InvalidKeyVariant), + matches!(error, Error::InvalidKeyVariant(Key::URef(_))), "Unexpected error {:?}", error ); @@ -272,7 +260,7 @@ fn should_not_panic_when_calling_session_contract_by_uref() { fn should_not_panic_when_calling_payment_contract_by_uref() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -281,17 +269,15 @@ fn should_not_panic_when_calling_payment_contract_by_uref() { ) .build(); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::new()) - .with_stored_payment_named_key(ACCESS_KEY, ENTRY_POINT_NAME, RuntimeArgs::new()) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::new()) + .with_stored_payment_named_key(ACCESS_KEY, ENTRY_POINT_NAME, RuntimeArgs::new()) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(install_exec_request).expect_success().commit(); @@ -300,14 +286,12 @@ fn should_not_panic_when_calling_payment_contract_by_uref() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); assert!( - matches!(error, Error::InvalidKeyVariant), + matches!(error, Error::InvalidKeyVariant(Key::URef(_))), "Unexpected error {:?}", error ); @@ -318,7 +302,7 @@ fn should_not_panic_when_calling_payment_contract_by_uref() { fn should_not_panic_when_calling_contract_package_by_uref() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -327,24 +311,22 @@ fn should_not_panic_when_calling_contract_package_by_uref() { ) .build(); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_stored_versioned_contract_by_name( - ACCESS_KEY, - None, - ENTRY_POINT_NAME, - RuntimeArgs::default(), - ) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_stored_versioned_contract_by_name( + ACCESS_KEY, + None, + ENTRY_POINT_NAME, + RuntimeArgs::default(), + ) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *CALL_STORED_CONTRACT_OVERHEAD, + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(install_exec_request).expect_success().commit(); @@ -353,14 +335,12 @@ fn should_not_panic_when_calling_contract_package_by_uref() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); assert!( - matches!(error, Error::InvalidKeyVariant), + matches!(error, Error::InvalidKeyVariant(Key::URef(_))), "Unexpected error {:?}", error ); @@ -371,7 +351,7 @@ fn should_not_panic_when_calling_contract_package_by_uref() { fn should_not_panic_when_calling_payment_versioned_contract_by_uref() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -380,22 +360,20 @@ fn should_not_panic_when_calling_payment_versioned_contract_by_uref() { ) .build(); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::new()) - .with_stored_versioned_payment_contract_by_name( - ACCESS_KEY, - None, - ENTRY_POINT_NAME, - RuntimeArgs::new(), - ) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::new()) + .with_stored_versioned_payment_contract_by_name( + ACCESS_KEY, + None, + ENTRY_POINT_NAME, + RuntimeArgs::new(), + ) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(install_exec_request).expect_success().commit(); @@ -404,13 +382,11 @@ fn should_not_panic_when_calling_payment_versioned_contract_by_uref() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); assert!( - matches!(error, Error::InvalidKeyVariant), + matches!(error, Error::InvalidKeyVariant(Key::URef(_))), "Unexpected error {:?}", error ); @@ -438,30 +414,26 @@ fn do_nothing_without_memory() -> Vec { fn should_not_panic_when_calling_module_without_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(do_nothing_without_memory(), RuntimeArgs::new()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT, - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(do_nothing_without_memory(), RuntimeArgs::new()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT, + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).commit(); let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1152.rs b/execution_engine_testing/tests/src/test/regression/ee_1152.rs index 3ebac102f1..c435de9f77 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1152.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1152.rs @@ -37,17 +37,17 @@ fn should_run_ee_1152_regression_test() { let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_STAKE.into()), + Motes::new(VALIDATOR_STAKE), DelegationRate::zero(), )), ); let validator_2 = GenesisAccount::account( DELEGATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_STAKE.into()), + Motes::new(VALIDATOR_STAKE), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1160.rs b/execution_engine_testing/tests/src/test/regression/ee_1160.rs index 0dabba7028..791301a598 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1160.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1160.rs @@ -1,11 +1,9 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_INITIAL_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + DEFAULT_ACCOUNT_INITIAL_BALANCE, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::WASMLESS_TRANSFER_FIXED_GAS_PRICE; -use casper_types::{ - account::AccountHash, runtime_args, system::mint, Gas, MintCosts, Motes, SystemConfig, U512, -}; +use casper_types::{account::AccountHash, Gas, MintCosts, Motes, SystemConfig, U512}; const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); @@ -23,38 +21,21 @@ fn ee_1160_wasmless_transfer_should_empty_account() { U512::from(DEFAULT_ACCOUNT_INITIAL_BALANCE) - wasmless_transfer_cost.value(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) .expect("should get default_account"); - let no_wasm_transfer_request_1 = { - let wasmless_transfer_args = runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => >::None - }; - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(wasmless_transfer_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(transfer_amount, ACCOUNT_1_ADDR).build(); builder - .exec(no_wasm_transfer_request_1) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request_1) + .expect_success(); let last_result = builder.get_exec_result_owned(0).unwrap(); - let last_result = &last_result[0]; - assert!(last_result.as_error().is_none(), "{:?}", last_result); + assert!(last_result.error().is_none(), "{:?}", last_result); assert!(!last_result.transfers().is_empty()); let default_account_balance_after = builder.get_purse_balance(default_account.main_purse()); @@ -77,7 +58,7 @@ fn ee_1160_transfer_larger_than_balance_should_fail() { + U512::one(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -85,24 +66,9 @@ fn ee_1160_transfer_larger_than_balance_should_fail() { let balance_before = builder.get_purse_balance(default_account.main_purse()); - let no_wasm_transfer_request_1 = { - let wasmless_transfer_args = runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => >::None - }; - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(wasmless_transfer_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - - builder.exec(no_wasm_transfer_request_1).commit(); + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(transfer_amount, ACCOUNT_1_ADDR).build(); + builder.transfer_and_commit(no_wasm_transfer_request_1); let balance_after = builder.get_purse_balance(default_account.main_purse()); @@ -114,7 +80,6 @@ fn ee_1160_transfer_larger_than_balance_should_fail() { .expect("gas overflow"); let last_result = builder.get_exec_result_owned(0).unwrap(); - let last_result = &last_result[0]; assert_eq!( balance_before - wasmless_transfer_motes.value(), balance_after @@ -123,7 +88,7 @@ fn ee_1160_transfer_larger_than_balance_should_fail() { //assert_eq!(last_result.cost(), wasmless_transfer_gas_cost); assert!( - last_result.as_error().is_some(), + last_result.error().is_some(), "Expected error but last result is {:?}", last_result ); @@ -139,7 +104,7 @@ fn ee_1160_large_wasmless_transfer_should_avoid_overflow() { let transfer_amount = U512::max_value(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -147,24 +112,9 @@ fn ee_1160_large_wasmless_transfer_should_avoid_overflow() { let balance_before = builder.get_purse_balance(default_account.main_purse()); - let no_wasm_transfer_request_1 = { - let wasmless_transfer_args = runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => >::None - }; - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(wasmless_transfer_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - - builder.exec(no_wasm_transfer_request_1).commit(); + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(transfer_amount, ACCOUNT_1_ADDR).build(); + builder.transfer_and_commit(no_wasm_transfer_request_1); let balance_after = builder.get_purse_balance(default_account.main_purse()); @@ -181,12 +131,11 @@ fn ee_1160_large_wasmless_transfer_should_avoid_overflow() { ); let last_result = builder.get_exec_result_owned(0).unwrap(); - let last_result = &last_result[0]; // TODO: reenable when new payment logic is added // assert_eq!(last_result.cost(), wasmless_transfer_gas_cost); assert!( - last_result.as_error().is_some(), + last_result.error().is_some(), "Expected error but last result is {:?}", last_result ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1163.rs b/execution_engine_testing/tests/src/test/regression/ee_1163.rs index fd37003d62..47cd8b9145 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1163.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1163.rs @@ -1,30 +1,23 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_GAS_PRICE, PRODUCTION_RUN_GENESIS_REQUEST, + LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; -use casper_execution_engine::engine_state::{ - Error, ExecuteRequest, WASMLESS_TRANSFER_FIXED_GAS_PRICE, -}; -use casper_storage::system::transfer::TransferError; +use casper_execution_engine::engine_state::{Error, WASMLESS_TRANSFER_FIXED_GAS_PRICE}; +use casper_storage::{data_access_layer::TransferRequest, system::transfer::TransferError}; use casper_types::{ - account::AccountHash, - runtime_args, - system::{handle_payment, mint}, - Gas, Motes, RuntimeArgs, SystemConfig, U512, + account::AccountHash, system::handle_payment, Gas, Motes, RuntimeArgs, SystemConfig, U512, }; -const PRIORITIZED_GAS_PRICE: u64 = DEFAULT_GAS_PRICE * 7; -const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); +// const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder } fn should_charge_for_user_error( builder: &mut LmdbWasmTestBuilder, - request: ExecuteRequest, + request: TransferRequest, ) -> Error { let transfer_cost = Gas::from(SystemConfig::default().mint_costs().transfer); let transfer_cost_motes = @@ -37,17 +30,14 @@ fn should_charge_for_user_error( let purse_balance_before = builder.get_purse_balance(main_purse); let proposer_purse_balance_before = builder.get_proposer_purse_balance(); - builder.exec(request).commit(); + builder.transfer_and_commit(request); let purse_balance_after = builder.get_purse_balance(main_purse); let proposer_purse_balance_after = builder.get_proposer_purse_balance(); let response = builder .get_exec_result_owned(0) - .expect("should have result") - .get(0) - .cloned() - .expect("should have first result"); + .expect("should have result"); // TODO: reenable when new payment logic is added // assert_eq!(response.cost(), transfer_cost); assert_eq!( @@ -72,99 +62,52 @@ fn should_charge_for_user_error( assert_eq!(payment_purse_balance, U512::zero()); - response.as_error().cloned().expect("should have error") -} - -#[ignore] -#[test] -fn shouldnt_consider_gas_price_when_calculating_minimum_balance() { - let id: Option = None; - - let create_account_request = { - let transfer_amount = - Motes::new(U512::from(SystemConfig::default().mint_costs().transfer) + U512::one()); - - let transfer_args = runtime_args! { - - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => transfer_amount.value(), - mint::ARG_ID => id, - }; - - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build() - }; - - let transfer_request = { - let transfer_amount = Motes::new(U512::one()); - - let transfer_args = runtime_args! { - mint::ARG_TARGET => *DEFAULT_ACCOUNT_ADDR, - mint::ARG_AMOUNT => transfer_amount.value(), - mint::ARG_ID => id, - }; - - let deploy_item = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(transfer_args) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) - .with_gas_price(PRIORITIZED_GAS_PRICE) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - - let mut builder = setup(); - builder - .exec(create_account_request) - .expect_success() - .commit(); - builder.exec(transfer_request).expect_success().commit(); + response.error().cloned().expect("should have error") } +// TODO: reenable when new payment logic is added #[ignore] #[test] fn should_properly_charge_fixed_cost_with_nondefault_gas_price() { - // implies 1:1 gas/motes conversion rate regardless of gas price - let transfer_cost_motes = Motes::new(U512::from(SystemConfig::default().mint_costs().transfer)); - - let transfer_amount = Motes::new(U512::one()); - - let id: Option = None; - - let transfer_args = runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => transfer_amount.value(), - mint::ARG_ID => id, - }; - - let transfer_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(transfer_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .with_gas_price(PRIORITIZED_GAS_PRICE) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - - let mut builder = setup(); - let default_account = builder - .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) - .expect("should have default account"); - let main_purse = default_account.main_purse(); - let purse_balance_before = builder.get_purse_balance(main_purse); - let proposer_purse_balance_before = builder.get_proposer_purse_balance(); - - builder.exec(transfer_request).commit(); - - let purse_balance_after = builder.get_purse_balance(main_purse); - let proposer_purse_balance_after = builder.get_proposer_purse_balance(); - - // TODO: reenable when new payment logic is added - // let transfer_cost = Gas::from(DEFAULT_WASMLESS_TRANSFER_COST); + // // implies 1:1 gas/motes conversion rate regardless of gas price + // let transfer_cost_motes = Motes::new(U512::from(MintCosts::default().transfer)); + // + // let transfer_amount = Motes::new(U512::one()); + // + // let id: Option = None; + // + // let transfer_args = runtime_args! { + // mint::ARG_TARGET => ACCOUNT_1_ADDR, + // mint::ARG_AMOUNT => transfer_amount.value(), + // mint::ARG_ID => id, + // }; + // + // let transfer_request = { + // let deploy_item = DeployItemBuilder::new() + // .with_address(*DEFAULT_ACCOUNT_ADDR) + // .with_empty_payment_bytes(runtime_args! {}) + // .with_transfer_args(transfer_args) + // .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + // .with_deploy_hash([42; 32]) + // .with_gas_price(PRIORITIZED_GAS_PRICE) + // .build(); + // ExecuteRequestBuilder::from_deploy_item(&deploy_item).build() + // }; + // + // let mut builder = setup(); + // let default_account = builder + // .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) + // .expect("should have default account"); + // let main_purse = default_account.main_purse(); + // let purse_balance_before = builder.get_purse_balance(main_purse); + // let proposer_purse_balance_before = builder.get_proposer_purse_balance(); + // + // builder.transfer(transfer_request).commit(); + // + // let purse_balance_after = builder.get_purse_balance(main_purse); + // let proposer_purse_balance_after = builder.get_proposer_purse_balance(); + // + // let transfer_cost = Gas::from(MintCosts::default().transfer); // let response = builder // .get_exec_result_owned(0) // .expect("should have result") @@ -177,22 +120,23 @@ fn should_properly_charge_fixed_cost_with_nondefault_gas_price() { // "expected actual cost is {}", // transfer_cost // ); - assert_eq!( - purse_balance_before - transfer_cost_motes.value() - transfer_amount.value(), - purse_balance_after - ); - assert_eq!( - proposer_purse_balance_before + transfer_cost_motes.value(), - proposer_purse_balance_after - ); + // assert_eq!( + // purse_balance_before - transfer_cost_motes.value() - transfer_amount.value(), + // purse_balance_after + // ); + // assert_eq!( + // proposer_purse_balance_before + transfer_cost_motes.value(), + // proposer_purse_balance_after + // ); } #[ignore] #[test] fn should_charge_for_wasmless_transfer_missing_args() { let transfer_args = RuntimeArgs::new(); - let transfer_request = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build(); + let transfer_request = TransferRequestBuilder::new(1, AccountHash::default()) + .with_args(transfer_args) + .build(); let mut builder = setup(); let error = should_charge_for_user_error(&mut builder, transfer_request); @@ -212,16 +156,7 @@ fn should_charge_for_wasmless_transfer_invalid_purse() { .expect("should have default account"); let main_purse = default_account.main_purse(); - let id: Option = None; - - let transfer_args = runtime_args! { - mint::ARG_TARGET => main_purse, - mint::ARG_AMOUNT => U512::one(), - mint::ARG_ID => id, - }; - - let transfer_request = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build(); + let transfer_request = TransferRequestBuilder::new(1, main_purse).build(); let error = should_charge_for_user_error(&mut builder, transfer_request); assert!(matches!( diff --git a/execution_engine_testing/tests/src/test/regression/ee_1174.rs b/execution_engine_testing/tests/src/test/regression/ee_1174.rs index ee5c59fcf3..cc5d833bd1 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1174.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1174.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; @@ -21,7 +21,7 @@ fn should_run_ee_1174_delegation_rate_too_high() { let bid_amount = U512::one(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let auction = builder.get_auction_contract_hash(); @@ -44,9 +44,7 @@ fn should_run_ee_1174_delegation_rate_too_high() { let error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .cloned() .expect("should have error"); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1217.rs b/execution_engine_testing/tests/src/test/regression/ee_1217.rs index ff530caa2d..a5f12aa12e 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1217.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1217.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{ engine_state::{engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, Error as CoreError}, @@ -55,7 +55,7 @@ fn should_fail_to_add_bid_from_stored_session_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(store_call_auction_request) @@ -97,7 +97,7 @@ fn should_fail_to_add_bid_from_stored_contract_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(store_call_auction_request) @@ -150,7 +150,7 @@ fn should_fail_to_withdraw_bid_from_stored_session_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(add_bid_request).commit().expect_success(); @@ -205,7 +205,7 @@ fn should_fail_to_withdraw_bid_from_stored_contract_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(add_bid_request).commit().expect_success(); @@ -280,7 +280,7 @@ fn should_fail_to_delegate_from_stored_session_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(validator_fund_request) @@ -360,7 +360,7 @@ fn should_fail_to_delegate_from_stored_contract_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(validator_fund_request) @@ -428,7 +428,7 @@ fn should_fail_to_undelegate_from_stored_session_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let delegate_request = ExecuteRequestBuilder::contract_call_by_hash( *DEFAULT_ACCOUNT_ADDR, @@ -522,7 +522,7 @@ fn should_fail_to_undelegate_from_stored_contract_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let delegate_request = ExecuteRequestBuilder::contract_call_by_hash( *DEFAULT_ACCOUNT_ADDR, @@ -607,7 +607,7 @@ fn should_fail_to_activate_bid_from_stored_session_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(add_bid_request).commit().expect_success(); builder.exec(withdraw_bid_request).commit().expect_success(); @@ -623,7 +623,7 @@ fn should_fail_to_activate_bid_from_stored_session_code() { None, CONTRACT_ACTIVATE_BID_ENTRYPOINT_SESSION, runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => default_public_key_arg, + auction::ARG_VALIDATOR => default_public_key_arg, }, ) .build(); @@ -673,7 +673,7 @@ fn should_fail_to_activate_bid_from_stored_contract_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(add_bid_request).commit().expect_success(); builder.exec(withdraw_bid_request).commit().expect_success(); @@ -689,7 +689,7 @@ fn should_fail_to_activate_bid_from_stored_contract_code() { None, CONTRACT_ACTIVATE_BID_ENTRYPOINT_CONTRACT, runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => default_public_key_arg, + auction::ARG_VALIDATOR => default_public_key_arg, }, ) .build(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_1225.rs b/execution_engine_testing/tests/src/test/regression/ee_1225.rs index dd2e09ce23..aac90cd7a8 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_1225.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_1225.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, RuntimeArgs}; @@ -11,27 +11,26 @@ const DO_NOTHING_CONTRACT: &str = "do_nothing.wasm"; #[should_panic(expected = "Finalization")] #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_ee_1225_verify_finalize_payment_invariants() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_payment_code( - EE_1225_REGRESSION_CONTRACT, - runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT, - }, - ) - .with_session_code(DO_NOTHING_CONTRACT, RuntimeArgs::default()) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([2; 32]) - .build(); + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_payment_code( + EE_1225_REGRESSION_CONTRACT, + runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT, + }, + ) + .with_session_code(DO_NOTHING_CONTRACT, RuntimeArgs::default()) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([2; 32]) + .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); builder.exec(exec_request).expect_success().commit(); } diff --git a/execution_engine_testing/tests/src/test/regression/ee_221.rs b/execution_engine_testing/tests/src/test/regression/ee_221.rs index 906cbdd96c..8dde2173f0 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_221.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_221.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -20,7 +19,7 @@ fn should_run_ee_221_get_uref_regression_test() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_401.rs b/execution_engine_testing/tests/src/test/regression/ee_401.rs index 6cf99a2090..1f3c6dca04 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_401.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_401.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -25,7 +24,7 @@ fn should_execute_contracts_which_provide_extra_urefs() { .build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); builder.exec(exec_request_2).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_441.rs b/execution_engine_testing/tests/src/test/regression/ee_441.rs index af29e95cd5..b0ee4393e5 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_441.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_441.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, Key, URef}; @@ -16,25 +16,23 @@ fn get_uref(key: Key) -> URef { fn do_pass(pass: &str) -> (URef, URef) { // This test runs a contract that's after every call extends the same key with // more data - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_session_code( - EE_441_RNG_STATE, - runtime_args! { - "flag" => pass, - }, - ) - .with_deploy_hash([1u8; 32]) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_session_code( + EE_441_RNG_STATE, + runtime_args! { + "flag" => pass, + }, + ) + .with_deploy_hash([1u8; 32]) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_460.rs b/execution_engine_testing/tests/src/test/regression/ee_460.rs index 2581b3a8ce..78f88dd242 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_460.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_460.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{ addressable_entity::EntityKindTag, execution::TransformKindV2, runtime_args, Key, U512, @@ -21,7 +20,7 @@ fn should_run_ee_460_no_side_effects_on_error_regression() { .build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_468.rs b/execution_engine_testing/tests/src/test/regression/ee_468.rs index 624a6ef9f5..95fc6ce32b 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_468.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_468.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -16,7 +15,7 @@ fn should_not_fail_deserializing() { ) .build(); let is_error = LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit() .is_error(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_470.rs b/execution_engine_testing/tests/src/test/regression/ee_470.rs index 8caa2c9cf1..546b2a8bfa 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_470.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_470.rs @@ -1,8 +1,7 @@ use std::sync::Arc; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_storage::global_state::{ state::{lmdb::LmdbGlobalState, StateProvider}, @@ -27,7 +26,7 @@ fn regression_test_genesis_hash_mismatch() { .build(); // Step 1. - let builder = builder_base.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + let builder = builder_base.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // This is trie's post state hash after calling run_genesis endpoint. // Step 1a) @@ -63,7 +62,7 @@ fn regression_test_genesis_hash_mismatch() { // No step 3. // Step 4. - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Step 4a) let second_genesis_run_hash = builder.get_genesis_hash(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_532.rs b/execution_engine_testing/tests/src/test/regression/ee_532.rs index 373aff0b04..6998c3425f 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_532.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_532.rs @@ -1,5 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::Error; use casper_storage::tracking_copy::TrackingCopyError; @@ -20,28 +20,25 @@ fn should_run_ee_532_non_existent_account_regression_test() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); let deploy_result = builder .get_exec_result_owned(0) - .expect("should have exec response") - .get(0) - .cloned() - .expect("should have at least one deploy result"); + .expect("should have exec response"); assert!( deploy_result.has_precondition_failure(), "expected precondition failure" ); - let message = deploy_result.as_error().map(|err| format!("{}", err)); + let message = deploy_result.error().map(|err| format!("{}", err)); assert_eq!( message, Some(format!( "{}", - Error::TrackingCopy(TrackingCopyError::AccountNotFound(UNKNOWN_ADDR.into())) + Error::TrackingCopy(TrackingCopyError::KeyNotFound(UNKNOWN_ADDR.into())) )), "expected Error::Authorization" ) diff --git a/execution_engine_testing/tests/src/test/regression/ee_536.rs b/execution_engine_testing/tests/src/test/regression/ee_536.rs index d2421bf300..8761d8667c 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_536.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_536.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -18,7 +17,7 @@ fn should_run_ee_536_associated_account_management_regression() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_539.rs b/execution_engine_testing/tests/src/test/regression/ee_539.rs index 1559479a46..f6a0a58424 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_539.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_539.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{addressable_entity::Weight, runtime_args}; @@ -22,7 +21,7 @@ fn should_run_ee_539_serialize_action_thresholds_regression() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/ee_549.rs b/execution_engine_testing/tests/src/test/regression/ee_549.rs index afc56931db..df1743d9da 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_549.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_549.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -19,7 +18,7 @@ fn should_run_ee_549_set_refund_regression() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request); // Execution should encounter an error because set_refund diff --git a/execution_engine_testing/tests/src/test/regression/ee_550.rs b/execution_engine_testing/tests/src/test/regression/ee_550.rs index 10982ffffc..0e869dc6f6 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_550.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_550.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args}; @@ -24,25 +24,23 @@ fn should_run_ee_550_remove_with_saturated_threshold_regression() { ) .build(); - let exec_request_2 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code( - CONTRACT_EE_550_REGRESSION, - runtime_args! { ARG_PASS => String::from(PASS_TEST_REMOVE) }, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, AccountHash::new(KEY_2_ADDR)]) - .with_deploy_hash(DEPLOY_HASH) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code( + CONTRACT_EE_550_REGRESSION, + runtime_args! { ARG_PASS => String::from(PASS_TEST_REMOVE) }, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, AccountHash::new(KEY_2_ADDR)]) + .with_deploy_hash(DEPLOY_HASH) + .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() @@ -61,25 +59,23 @@ fn should_run_ee_550_update_with_saturated_threshold_regression() { ) .build(); - let exec_request_2 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code( - CONTRACT_EE_550_REGRESSION, - runtime_args! { ARG_PASS => String::from(PASS_TEST_UPDATE) }, - ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, AccountHash::new(KEY_2_ADDR)]) - .with_deploy_hash(DEPLOY_HASH) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code( + CONTRACT_EE_550_REGRESSION, + runtime_args! { ARG_PASS => String::from(PASS_TEST_UPDATE) }, + ) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR, AccountHash::new(KEY_2_ADDR)]) + .with_deploy_hash(DEPLOY_HASH) + .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let exec_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() diff --git a/execution_engine_testing/tests/src/test/regression/ee_572.rs b/execution_engine_testing/tests/src/test/regression/ee_572.rs index 330fc14a64..bcb05d48ed 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_572.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_572.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ - utils, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args, Key, U512}; @@ -48,7 +48,7 @@ fn should_run_ee_572_regression() { // Create Accounts builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit(); @@ -68,6 +68,7 @@ fn should_run_ee_572_regression() { .expect("Could not find contract pointer") }; + // Attempt to forge a new URef with escalated privileges let exec_request_4 = ExecuteRequestBuilder::standard( ACCOUNT_2_ADDR, CONTRACT_ESCALATE, @@ -78,15 +79,15 @@ fn should_run_ee_572_regression() { .build(); // Attempt to forge a new URef with escalated privileges - let response = builder + let _ = builder .exec(exec_request_4) .get_exec_result_owned(3) .expect("should have a response"); - let error_message = utils::get_error_message(response); + let error_message = builder.get_error_message().unwrap(); assert!( - error_message.contains("ForgedReference"), + error_message.contains("Forged reference"), "{}", error_message ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_584.rs b/execution_engine_testing/tests/src/test/regression/ee_584.rs index a859402ede..f2d532e8d0 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_584.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_584.rs @@ -1,13 +1,13 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{execution::TransformKindV2, RuntimeArgs, StoredValue}; const CONTRACT_EE_584_REGRESSION: &str = "ee_584_regression.wasm"; #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_ee_584_no_errored_session_transforms() { let exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -19,7 +19,7 @@ fn should_run_ee_584_no_errored_session_transforms() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request); assert!(builder.is_error()); diff --git a/execution_engine_testing/tests/src/test/regression/ee_597.rs b/execution_engine_testing/tests/src/test/regression/ee_597.rs index c454708352..0d59bfcd09 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_597.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_597.rs @@ -23,11 +23,8 @@ const VALID_BALANCE: u64 = MINIMUM_ACCOUNT_CREATION_BALANCE; fn should_fail_when_bonding_amount_is_zero_ee_597_regression() { let accounts = { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); - let account = GenesisAccount::account( - VALID_PUBLIC_KEY.clone(), - Motes::new(VALID_BALANCE.into()), - None, - ); + let account = + GenesisAccount::account(VALID_PUBLIC_KEY.clone(), Motes::new(VALID_BALANCE), None); tmp.push(account); tmp }; @@ -47,11 +44,7 @@ fn should_fail_when_bonding_amount_is_zero_ee_597_regression() { .exec(exec_request) .commit(); - let response = builder - .get_exec_result_owned(0) - .expect("should have a response"); - - let error_message = utils::get_error_message(response); + let error_message = builder.get_error_message().expect("should have a result"); // Error::BondTooSmall => 5, assert!( diff --git a/execution_engine_testing/tests/src/test/regression/ee_598.rs b/execution_engine_testing/tests/src/test/regression/ee_598.rs index c8b414692b..ef42fa1663 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_598.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_598.rs @@ -38,9 +38,9 @@ fn should_handle_unbond_for_more_than_stake_as_full_unbond_of_stake_ee_598_regre let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account = GenesisAccount::account( public_key, - Motes::new(GENESIS_VALIDATOR_STAKE.into()) * Motes::new(2.into()), + Motes::new(GENESIS_VALIDATOR_STAKE) * Motes::new(2), Some(GenesisValidator::new( - Motes::new(GENESIS_VALIDATOR_STAKE.into()), + Motes::new(GENESIS_VALIDATOR_STAKE), DelegationRate::zero(), )), ); @@ -60,22 +60,20 @@ fn should_handle_unbond_for_more_than_stake_as_full_unbond_of_stake_ee_598_regre }, ) .build(); - let combined_bond_and_unbond_request = { - let deploy = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *ACCOUNT_1_FUND }) - .with_session_code( - "ee_598_regression.wasm", - runtime_args! { - ARG_AMOUNT => *ACCOUNT_1_BOND, - ARG_PUBLIC_KEY => ACCOUNT_1_PK.clone(), - }, - ) - .with_deploy_hash([2u8; 32]) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy).build() - }; + let deploy = DeployItemBuilder::new() + .with_address(*ACCOUNT_1_ADDR) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *ACCOUNT_1_FUND }) + .with_session_code( + "ee_598_regression.wasm", + runtime_args! { + ARG_AMOUNT => *ACCOUNT_1_BOND, + ARG_PUBLIC_KEY => ACCOUNT_1_PK.clone(), + }, + ) + .with_deploy_hash([2u8; 32]) + .with_authorization_keys(&[*ACCOUNT_1_ADDR]) + .build(); + let combined_bond_and_unbond_request = ExecuteRequestBuilder::from_deploy_item(&deploy).build(); let mut builder = LmdbWasmTestBuilder::default(); builder.run_genesis(run_genesis_request); diff --git a/execution_engine_testing/tests/src/test/regression/ee_599.rs b/execution_engine_testing/tests/src/test/regression/ee_599.rs index 4b0dd4190a..82e468bbdb 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_599.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_599.rs @@ -2,14 +2,14 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{account::AccountHash, runtime_args, U512}; const CONTRACT_EE_599_REGRESSION: &str = "ee_599_regression.wasm"; const CONTRACT_TRANSFER_TO_ACCOUNT: &str = "transfer_to_account_u512.wasm"; const DONATION_PURSE_COPY_KEY: &str = "donation_purse_copy"; -const EXPECTED_ERROR: &str = "ForgedReference"; +const EXPECTED_ERROR: &str = "Forged reference"; const TRANSFER_FUNDS_KEY: &str = "transfer_funds"; const VICTIM_ADDR: AccountHash = AccountHash::new([42; 32]); @@ -36,7 +36,7 @@ fn setup() -> LmdbWasmTestBuilder { }; let mut ctx = LmdbWasmTestBuilder::default(); - ctx.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + ctx.run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() @@ -87,7 +87,7 @@ fn should_not_be_able_to_transfer_funds_with_transfer_purse_to_purse() { let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; - let error_msg = builder.exec_error_message(0).expect("should have error"); + let error_msg = builder.get_error_message().expect("should have error"); assert!( error_msg.contains(EXPECTED_ERROR), "Got error: {}", @@ -147,7 +147,7 @@ fn should_not_be_able_to_transfer_funds_with_transfer_from_purse_to_account() { let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; - let error_msg = builder.exec_error_message(0).expect("should have error"); + let error_msg = builder.get_error_message().expect("should have error"); assert!( error_msg.contains(EXPECTED_ERROR), "Got error: {}", @@ -215,7 +215,7 @@ fn should_not_be_able_to_transfer_funds_with_transfer_to_account() { let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; - let error_msg = builder.exec_error_message(0).expect("should have error"); + let error_msg = builder.get_error_message().expect("should have error"); assert!( error_msg.contains(EXPECTED_ERROR), "Got error: {}", @@ -277,7 +277,7 @@ fn should_not_be_able_to_get_main_purse_in_invalid_builder() { let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; - let error_msg = builder.exec_error_message(0).expect("should have error"); + let error_msg = builder.get_error_message().expect("should have error"); assert!( error_msg.contains(EXPECTED_ERROR), "Got error: {}", diff --git a/execution_engine_testing/tests/src/test/regression/ee_601.rs b/execution_engine_testing/tests/src/test/regression/ee_601.rs index 3b1742ccd1..c0160a4ba8 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_601.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_601.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{ addressable_entity::NamedKeyAddr, execution::TransformKindV2, runtime_args, CLValue, @@ -14,25 +14,23 @@ const ARG_AMOUNT: &str = "amount"; fn should_run_ee_601_pay_session_new_uref_collision() { let genesis_account_hash = *DEFAULT_ACCOUNT_ADDR; - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_deploy_hash([1; 32]) - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_payment_code( - "ee_601_regression.wasm", - runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }, - ) - .with_session_code("ee_601_regression.wasm", RuntimeArgs::default()) - .with_authorization_keys(&[genesis_account_hash]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_deploy_hash([1; 32]) + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_payment_code( + "ee_601_regression.wasm", + runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }, + ) + .with_session_code("ee_601_regression.wasm", RuntimeArgs::default()) + .with_authorization_keys(&[genesis_account_hash]) + .build(); + + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request); let entity_hash = builder diff --git a/execution_engine_testing/tests/src/test/regression/ee_771.rs b/execution_engine_testing/tests/src/test/regression/ee_771.rs index 9ee1e9850d..8786daaab1 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_771.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_771.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -18,15 +17,15 @@ fn should_run_ee_771_regression() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); - let response = builder + let exec_result = builder .get_exec_result_owned(0) .expect("should have a response"); - let error = response[0].as_error().expect("should have error"); + let error = exec_result.error().expect("should have error"); assert_eq!( format!("{}", error), "Function not found: functiondoesnotexist" diff --git a/execution_engine_testing/tests/src/test/regression/ee_890.rs b/execution_engine_testing/tests/src/test/regression/ee_890.rs index 0d090a499f..ce7be9a44e 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_890.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_890.rs @@ -2,7 +2,7 @@ use casper_wasm::{self, builder}; use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_types::{addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, RuntimeArgs}; @@ -40,24 +40,24 @@ fn make_do_nothing_with_start() -> Vec { fn should_run_ee_890_gracefully_reject_start_node_in_session() { let wasm_binary = make_do_nothing_with_start(); - let deploy_1 = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_bytes(wasm_binary, RuntimeArgs::new()) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([123; 32]) .build(); - let exec_request_1 = ExecuteRequestBuilder::new().push_deploy(deploy_1).build(); + let exec_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .commit(); - let message = builder.exec_error_message(0).expect("should fail"); + let message = builder.get_error_message().expect("should fail"); assert!( - message.contains("UnsupportedWasmStart"), + message.contains("Unsupported Wasm start"), "Error message {:?} does not contain expected pattern", message ); @@ -68,7 +68,7 @@ fn should_run_ee_890_gracefully_reject_start_node_in_session() { fn should_run_ee_890_gracefully_reject_start_node_in_payment() { let wasm_binary = make_do_nothing_with_start(); - let deploy_1 = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code(DO_NOTHING_WASM, RuntimeArgs::new()) .with_payment_bytes(wasm_binary, RuntimeArgs::new()) @@ -76,16 +76,16 @@ fn should_run_ee_890_gracefully_reject_start_node_in_payment() { .with_deploy_hash([123; 32]) .build(); - let exec_request_1 = ExecuteRequestBuilder::new().push_deploy(deploy_1).build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) - .exec(exec_request_1) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) + .exec(exec_request) .commit(); - let message = builder.exec_error_message(0).expect("should fail"); + let message = builder.get_error_message().expect("should fail"); assert!( - message.contains("UnsupportedWasmStart"), + message.contains("Unsupported Wasm start"), "Error message {:?} does not contain expected pattern", message ); diff --git a/execution_engine_testing/tests/src/test/regression/ee_966.rs b/execution_engine_testing/tests/src/test/regression/ee_966.rs index 4656ca196b..ee472bf628 100644 --- a/execution_engine_testing/tests/src/test/regression/ee_966.rs +++ b/execution_engine_testing/tests/src/test/regression/ee_966.rs @@ -3,14 +3,11 @@ use casper_wasm::builder; use once_cell::sync::Lazy; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, - ARG_AMOUNT, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, - PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_execution_engine::{ - engine_state::{Error, ExecuteRequest}, - execution::ExecError, + DeployItemBuilder, ExecuteRequest, ExecuteRequestBuilder, LmdbWasmTestBuilder, + UpgradeRequestBuilder, ARG_AMOUNT, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, + DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, }; +use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, ApiError, EraId, HostFunctionCosts, MessageLimits, OpcodeCosts, ProtocolVersion, RuntimeArgs, StorageCosts, WasmConfig, @@ -31,13 +28,11 @@ static DOUBLED_WASM_MEMORY_LIMIT: Lazy = Lazy::new(|| { MessageLimits::default(), ) }); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - DEFAULT_PROTOCOL_VERSION.value().major, - DEFAULT_PROTOCOL_VERSION.value().minor, - DEFAULT_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + DEFAULT_PROTOCOL_VERSION.value().major, + DEFAULT_PROTOCOL_VERSION.value().minor, + DEFAULT_PROTOCOL_VERSION.value().patch + 1, +); fn make_session_code_with_memory_pages(initial_pages: u32, max_pages: Option) -> Vec { let module = builder::module() @@ -63,17 +58,17 @@ fn make_session_code_with_memory_pages(initial_pages: u32, max_pages: Option) -> ExecuteRequest { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_bytes(session_code, RuntimeArgs::new()) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + ExecuteRequestBuilder::from_deploy_item(&deploy_item).build() } #[ignore] @@ -86,7 +81,7 @@ fn should_run_ee_966_with_zero_min_and_zero_max_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit().expect_success(); } @@ -100,14 +95,14 @@ fn should_run_ee_966_cant_have_too_much_initial_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let exec_response = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = exec_response.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Interpreter(_))); } @@ -121,7 +116,7 @@ fn should_run_ee_966_should_request_exactly_maximum() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit().expect_success(); } @@ -135,7 +130,7 @@ fn should_run_ee_966_should_request_exactly_maximum_as_initial() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit().expect_success(); } @@ -152,14 +147,14 @@ fn should_run_ee_966_cant_have_too_much_max_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let exec_response = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = exec_response.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Interpreter(_))); } @@ -175,14 +170,14 @@ fn should_run_ee_966_cant_have_way_too_much_max_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let exec_response = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = exec_response.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Interpreter(_))); } @@ -196,14 +191,14 @@ fn should_run_ee_966_cant_have_larger_initial_than_max_memory() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let exec_response = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = exec_response.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Interpreter(_))); } @@ -219,14 +214,14 @@ fn should_run_ee_966_regression_fail_when_growing_mem_past_max() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let results = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = results.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Revert(ApiError::OutOfMemory))); } @@ -242,7 +237,7 @@ fn should_run_ee_966_regression_when_growing_mem_after_upgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).commit(); @@ -250,10 +245,10 @@ fn should_run_ee_966_regression_when_growing_mem_after_upgrade() { // This request should fail - as it's exceeding default memory limit // - let results = &builder + let exec_result = &builder .get_exec_result_owned(0) - .expect("should have exec response")[0]; - let error = results.as_error().expect("should have error"); + .expect("should have exec response"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Revert(ApiError::OutOfMemory))); // @@ -261,8 +256,8 @@ fn should_run_ee_966_regression_when_growing_mem_after_upgrade() { // let mut upgrade_request = UpgradeRequestBuilder::new() - .with_current_protocol_version(*DEFAULT_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(DEFAULT_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build(); @@ -284,7 +279,6 @@ fn should_run_ee_966_regression_when_growing_mem_after_upgrade() { CONTRACT_EE_966_REGRESSION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request_2).commit().expect_success(); diff --git a/execution_engine_testing/tests/src/test/regression/gh_1470.rs b/execution_engine_testing/tests/src/test/regression/gh_1470.rs index 38b41028ec..365d8ad6c6 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_1470.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_1470.rs @@ -1,14 +1,15 @@ use std::collections::BTreeMap; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_PUBLIC_KEY, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, UpgradeRequestBuilder, + DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ account::AccountHash, runtime_args, - system::{auction, auction::DelegationRate, mint}, + system::{auction, auction::DelegationRate}, AccessRights, AddressableEntityHash, CLTyped, CLValue, Digest, EraId, Key, PackageHash, ProtocolVersion, RuntimeArgs, StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, URef, U512, @@ -33,19 +34,13 @@ const PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V1_0_0; fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => MINIMUM_ACCOUNT_CREATION_BALANCE, - mint::ARG_ID => Some(42u64), - }, - ) - .build(); + let transfer = TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR) + .with_transfer_id(42) + .build(); - builder.exec(transfer).expect_success().commit(); + builder.transfer_and_commit(transfer).expect_success(); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -144,15 +139,10 @@ fn gh_1470_call_contract_should_verify_group_access() { builder.exec(call_contract_request).commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_contract_error = exec_response - .as_error() - .cloned() - .expect("should have error"); + let call_contract_error = exec_result.error().cloned().expect("should have error"); let call_versioned_contract_request = { let args = runtime_args! { @@ -164,12 +154,10 @@ fn gh_1470_call_contract_should_verify_group_access() { builder.exec(call_versioned_contract_request).commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_versioned_contract_error = exec_response.as_error().expect("should have error"); + let call_versioned_contract_error = exec_result.error().expect("should have error"); match (&call_contract_error, &call_versioned_contract_error) { (Error::Exec(ExecError::InvalidContext), Error::Exec(ExecError::InvalidContext)) => (), @@ -478,15 +466,10 @@ fn gh_1470_call_contract_should_verify_wrong_argument_types() { builder.exec(call_contract_request).commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_contract_error = exec_response - .as_error() - .cloned() - .expect("should have error"); + let call_contract_error = exec_result.error().cloned().expect("should have error"); let call_versioned_contract_request = { let args = runtime_args! { @@ -499,12 +482,10 @@ fn gh_1470_call_contract_should_verify_wrong_argument_types() { builder.exec(call_versioned_contract_request).commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_versioned_contract_error = exec_response.as_error().expect("should have error"); + let call_versioned_contract_error = exec_result.error().expect("should have error"); let expected = gh_1470_regression::Arg1Type::cl_type(); let found = gh_1470_regression::Arg3Type::cl_type(); @@ -588,15 +569,10 @@ fn gh_1470_call_contract_should_verify_wrong_optional_argument_types() { .expect_failure() .commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_contract_error = exec_response - .as_error() - .cloned() - .expect("should have error"); + let call_contract_error = exec_result.error().cloned().expect("should have error"); let call_versioned_contract_request = { let args = runtime_args! { @@ -609,12 +585,10 @@ fn gh_1470_call_contract_should_verify_wrong_optional_argument_types() { builder.exec(call_versioned_contract_request).commit(); - let response = builder + let exec_result = builder .get_last_exec_result() .expect("should have last response"); - assert_eq!(response.len(), 1); - let exec_response = response.last().expect("should have response"); - let call_versioned_contract_error = exec_response.as_error().expect("should have error"); + let call_versioned_contract_error = exec_result.error().expect("should have error"); let expected = gh_1470_regression::Arg3Type::cl_type(); let found = gh_1470_regression::Arg4Type::cl_type(); @@ -675,19 +649,11 @@ fn should_transfer_after_major_version_bump_from_1_2_0() { .upgrade(&mut upgrade_request) .expect_upgrade_success(); - let transfer_args = runtime_args! { - mint::ARG_AMOUNT => U512::one(), - mint::ARG_TARGET => AccountHash::new([3; 32]), - mint::ARG_ID => Some(1u64), - }; - - let transfer = ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args) - .with_protocol_version(new_protocol_version) + let transfer = TransferRequestBuilder::new(1, AccountHash::new([3; 32])) + .with_transfer_id(1) .build(); - println!("About to execute"); - - builder.exec(transfer).expect_success().commit(); + builder.transfer_and_commit(transfer).expect_success(); } #[ignore] @@ -696,12 +662,6 @@ fn should_transfer_after_minor_version_bump_from_1_2_0() { let (mut builder, lmdb_fixture_state, _temp_dir) = lmdb_fixture::builder_from_global_state_fixture(lmdb_fixture::RELEASE_1_3_1); - let transfer_args = runtime_args! { - mint::ARG_AMOUNT => U512::one(), - mint::ARG_TARGET => AccountHash::new([3; 32]), - mint::ARG_ID => Some(1u64), - }; - let current_protocol_version = lmdb_fixture_state.genesis_protocol_version(); let new_protocol_version = ProtocolVersion::from_parts( @@ -726,10 +686,10 @@ fn should_transfer_after_minor_version_bump_from_1_2_0() { .upgrade(&mut upgrade_request) .expect_upgrade_success(); - let transfer = ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args) - .with_protocol_version(new_protocol_version) + let transfer = TransferRequestBuilder::new(1, AccountHash::new([3; 32])) + .with_transfer_id(1) .build(); - builder.exec(transfer).expect_success().commit(); + builder.transfer_and_commit(transfer).expect_success(); } #[ignore] @@ -768,7 +728,6 @@ fn should_add_bid_after_major_bump() { auction::ARG_DELEGATION_RATE => BID_DELEGATION_RATE, }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(add_bid_request).expect_success().commit(); @@ -817,7 +776,6 @@ fn should_add_bid_after_minor_bump() { auction::ARG_DELEGATION_RATE => BID_DELEGATION_RATE, }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(add_bid_request).expect_success().commit(); @@ -862,7 +820,6 @@ fn should_wasm_transfer_after_major_bump() { ARG_TARGET => AccountHash::new([1; 32]), }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(wasm_transfer).expect_success().commit(); @@ -910,7 +867,6 @@ fn should_wasm_transfer_after_minor_bump() { ARG_TARGET => AccountHash::new([1; 32]), }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(wasm_transfer).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/regression/gh_1688.rs b/execution_engine_testing/tests/src/test/regression/gh_1688.rs index 8040483950..1dde09696c 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_1688.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_1688.rs @@ -1,8 +1,8 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; -use casper_execution_engine::engine_state::ExecuteRequest; +use casper_execution_engine::engine_state::DeployItem; use casper_types::{ runtime_args, system::standard_payment::ARG_AMOUNT, AddressableEntityHash, PackageHash, RuntimeArgs, @@ -17,7 +17,7 @@ const CONTRACT_HASH_KEY: &str = "contract_hash"; fn setup() -> (LmdbWasmTestBuilder, PackageHash, AddressableEntityHash) { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_contract_request_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -58,11 +58,11 @@ fn setup() -> (LmdbWasmTestBuilder, PackageHash, AddressableEntityHash) { (builder, contract_package_hash, entity_hash) } -fn test(request_builder: impl FnOnce(PackageHash, AddressableEntityHash) -> ExecuteRequest) { +fn test(deploy_item_builder: impl FnOnce(PackageHash, AddressableEntityHash) -> DeployItem) { let (mut builder, contract_package_hash, contract_hash) = setup(); - let exec_request = request_builder(contract_package_hash, contract_hash); - + let deploy_item = deploy_item_builder(contract_package_hash, contract_hash); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).expect_success().commit(); let account = builder @@ -90,7 +90,7 @@ fn test(request_builder: impl FnOnce(PackageHash, AddressableEntityHash) -> Exec #[test] fn should_run_gh_1688_regression_stored_versioned_contract_by_hash() { test(|contract_package_hash, _contract_hash| { - let deploy = DeployItemBuilder::new() + DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_stored_versioned_contract_by_hash( contract_package_hash.value(), @@ -98,11 +98,10 @@ fn should_run_gh_1688_regression_stored_versioned_contract_by_hash() { METHOD_PUT_KEY, RuntimeArgs::default(), ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() + .build() }); } @@ -110,7 +109,7 @@ fn should_run_gh_1688_regression_stored_versioned_contract_by_hash() { #[test] fn should_run_gh_1688_regression_stored_versioned_contract_by_name() { test(|_contract_package_hash, _contract_hash| { - let deploy = DeployItemBuilder::new() + DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_stored_versioned_contract_by_name( PACKAGE_KEY, @@ -118,12 +117,10 @@ fn should_run_gh_1688_regression_stored_versioned_contract_by_name() { METHOD_PUT_KEY, RuntimeArgs::default(), ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + .build() }); } @@ -131,15 +128,13 @@ fn should_run_gh_1688_regression_stored_versioned_contract_by_name() { #[test] fn should_run_gh_1688_regression_stored_contract_by_hash() { test(|_contract_package_hash, contract_hash| { - let deploy = DeployItemBuilder::new() + DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_stored_session_hash(contract_hash, METHOD_PUT_KEY, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + .build() }); } @@ -147,18 +142,16 @@ fn should_run_gh_1688_regression_stored_contract_by_hash() { #[test] fn should_run_gh_1688_regression_stored_contract_by_name() { test(|_contract_package_hash, _contract_hash| { - let deploy = DeployItemBuilder::new() + DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_stored_session_named_key( CONTRACT_HASH_KEY, METHOD_PUT_KEY, RuntimeArgs::default(), ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + .build() }); } diff --git a/execution_engine_testing/tests/src/test/regression/gh_1902.rs b/execution_engine_testing/tests/src/test/regression/gh_1902.rs index 229289d93a..e97f2fc753 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_1902.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_1902.rs @@ -1,20 +1,20 @@ +use num_rational::Ratio; use once_cell::sync::Lazy; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_ACCOUNT_PUBLIC_KEY, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_execution_engine::engine_state::{ - engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, ExecuteRequest, + DeployItemBuilder, ExecuteRequest, ExecuteRequestBuilder, LmdbWasmTestBuilder, + TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; +use casper_execution_engine::engine_state::engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT; use casper_types::{ account::AccountHash, runtime_args, system::{ auction::{self, DelegationRate}, - mint, standard_payment, + standard_payment, }, - AddressableEntity, Gas, PublicKey, SecretKey, U512, + AddressableEntity, FeeHandling, Gas, PublicKey, RefundHandling, SecretKey, U512, }; const BOND_AMOUNT: u64 = 42; @@ -29,16 +29,23 @@ static ACCOUNT_1_ADDR: Lazy = Lazy::new(|| AccountHash::from(&*ACCO fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - let id: Option = None; - let transfer_args_1 = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => id, - }; - let transfer_request_1 = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args_1).build(); - builder.exec(transfer_request_1).expect_success().commit(); + + let chainspec = builder + .chainspec() + .clone() + .with_refund_handling(RefundHandling::Refund { + refund_ratio: Ratio::new(1, 1), + }) + .with_fee_handling(FeeHandling::PayToProposer); + builder.with_chainspec(chainspec); + + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let transfer_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR).build(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); builder } @@ -47,21 +54,26 @@ fn exec_and_assert_costs( exec_request: ExecuteRequest, caller: AddressableEntity, expected_tokens_paid: U512, - expected_payment_charge: U512, + _payment_amount: U512, expected_gas_cost: Gas, ) { let balance_before = builder.get_purse_balance(caller.main_purse()); - let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); + let proposer_balance_before = builder.get_proposer_purse_balance(); builder.exec(exec_request).expect_success().commit(); let balance_after = builder.get_purse_balance(caller.main_purse()); - let transaction_fee = builder.get_proposer_purse_balance() - proposer_reward_starting_balance; - assert_eq!(transaction_fee, expected_payment_charge); + let proposer_fee = builder.get_proposer_purse_balance() - proposer_balance_before; - let expected = balance_before - expected_tokens_paid - transaction_fee; + assert_eq!( + proposer_fee, + expected_gas_cost.value(), + "with PayToProposer && 100% refund of unspent, the fee should equal the gas cost" + ); + + let expected = balance_before - expected_tokens_paid - proposer_fee; assert_eq!( balance_after, @@ -77,7 +89,8 @@ fn exec_and_assert_costs( } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_charge_for_create_purse_in_first_time_bond() { let mut builder = setup(); @@ -89,31 +102,35 @@ fn should_not_charge_for_create_purse_in_first_time_bond() { let bond_amount = U512::from(BOND_AMOUNT); // This amount should be enough to make first time add_bid call. let add_bid_cost = builder.get_auction_costs().add_bid; - let add_bid_payment_amount = U512::from(add_bid_cost); - - let add_bid_request = { - let sender = *DEFAULT_ACCOUNT_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_ADD_BID; - let payment_args = - runtime_args! { standard_payment::ARG_AMOUNT => add_bid_payment_amount, }; - let session_args = runtime_args! { - auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => bond_amount, - auction::ARG_DELEGATION_RATE => DELEGATION_RATE, - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash([43; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + + let pay_cost = builder + .chainspec() + .system_costs_config + .standard_payment_costs() + .pay; + + let add_bid_payment_amount = U512::from(add_bid_cost + pay_cost) * 2; + + let sender = *DEFAULT_ACCOUNT_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_ADD_BID; + let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => add_bid_payment_amount, }; + let session_args = runtime_args! { + auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => bond_amount, + auction::ARG_DELEGATION_RATE => DELEGATION_RATE, }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash([43; 32]) + .build(); + + let add_bid_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + exec_and_assert_costs( &mut builder, add_bid_request, @@ -127,30 +144,28 @@ fn should_not_charge_for_create_purse_in_first_time_bond() { let delegate_payment_amount = U512::from(delegate_cost); let delegate_amount = U512::from(DELEGATE_AMOUNT); - let delegate_request = { - let sender = *ACCOUNT_1_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_DELEGATE; - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => delegate_payment_amount, - }; - let session_args = runtime_args! { - auction::ARG_DELEGATOR => ACCOUNT_1_PUBLIC_KEY.clone(), - auction::ARG_VALIDATOR => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => delegate_amount, - }; - let deploy_hash = [55; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *ACCOUNT_1_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_DELEGATE; + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => delegate_payment_amount, + }; + let session_args = runtime_args! { + auction::ARG_DELEGATOR => ACCOUNT_1_PUBLIC_KEY.clone(), + auction::ARG_VALIDATOR => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => delegate_amount, }; + let deploy_hash = [55; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + + let delegate_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); exec_and_assert_costs( &mut builder, @@ -165,30 +180,28 @@ fn should_not_charge_for_create_purse_in_first_time_bond() { let undelegate_payment_amount = U512::from(undelegate_cost); let undelegate_amount = delegate_amount; - let undelegate_request = { - let sender = *ACCOUNT_1_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_UNDELEGATE; - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => undelegate_payment_amount, - }; - let session_args = runtime_args! { - auction::ARG_DELEGATOR => ACCOUNT_1_PUBLIC_KEY.clone(), - auction::ARG_VALIDATOR => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => undelegate_amount, - }; - let deploy_hash = [56; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *ACCOUNT_1_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_UNDELEGATE; + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => undelegate_payment_amount, }; + let session_args = runtime_args! { + auction::ARG_DELEGATOR => ACCOUNT_1_PUBLIC_KEY.clone(), + auction::ARG_VALIDATOR => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => undelegate_amount, + }; + let deploy_hash = [56; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash(deploy_hash) + .build(); + + let undelegate_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); exec_and_assert_costs( &mut builder, @@ -204,28 +217,26 @@ fn should_not_charge_for_create_purse_in_first_time_bond() { let withdraw_bid_cost = builder.get_auction_costs().withdraw_bid; let withdraw_bid_payment_amount = U512::from(withdraw_bid_cost); - let withdraw_bid_request = { - let sender = *DEFAULT_ACCOUNT_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_WITHDRAW_BID; - let payment_args = - runtime_args! { standard_payment::ARG_AMOUNT => withdraw_bid_payment_amount, }; - let session_args = runtime_args! { - auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => unbond_amount, - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash([58; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let sender = *DEFAULT_ACCOUNT_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_WITHDRAW_BID; + let payment_args = + runtime_args! { standard_payment::ARG_AMOUNT => withdraw_bid_payment_amount, }; + let session_args = runtime_args! { + auction::ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => unbond_amount, }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash([58; 32]) + .build(); + + let withdraw_bid_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + exec_and_assert_costs( &mut builder, withdraw_bid_request, diff --git a/execution_engine_testing/tests/src/test/regression/gh_1931.rs b/execution_engine_testing/tests/src/test/regression/gh_1931.rs index f531a18cf4..a58a25614c 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_1931.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_1931.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{RuntimeArgs, StoredValue}; @@ -11,9 +10,7 @@ const CONTRACT_PACKAGE_NAMED_KEY: &str = "do_nothing_package_hash"; #[test] fn should_query_contract_package() { let mut builder = LmdbWasmTestBuilder::default(); - builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) - .commit(); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()).commit(); let install_request = ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, CONTRACT_NAME, RuntimeArgs::new()) diff --git a/execution_engine_testing/tests/src/test/regression/gh_2280.rs b/execution_engine_testing/tests/src/test/regression/gh_2280.rs index 3b1f69acf1..d12cb06827 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_2280.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_2280.rs @@ -2,8 +2,8 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PROTOCOL_VERSION, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{ account::AccountHash, runtime_args, system::mint, AddressableEntityHash, EraId, Gas, @@ -45,14 +45,12 @@ const TOKEN_AMOUNT: u64 = 1_000_000; const ARG_PURSE_NAME: &str = "purse_name"; const TEST_PURSE_NAME: &str = "test"; -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); const HOST_FUNCTION_COST_CHANGE: HostFunctionCost = 13_730_593; // random prime number @@ -84,27 +82,24 @@ fn gh_2280_transfer_should_always_cost_the_same_gas() { // should be able to pay next time. let payment_amount = Motes::from_gas(gas_cost_1, 1).unwrap(); - let fund_request_2 = { - let deploy_hash: [u8; 32] = [55; 32]; - let faucet_args_2 = runtime_args! { - ARG_TARGET => *ACCOUNT_2_ADDR, - ARG_AMOUNT => TOKEN_AMOUNT, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, faucet_args_2) - // + default_create_purse_cost - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let deploy_hash: [u8; 32] = [55; 32]; + let faucet_args_2 = runtime_args! { + ARG_TARGET => *ACCOUNT_2_ADDR, + ARG_AMOUNT => TOKEN_AMOUNT, + }; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, faucet_args_2) + // + default_create_purse_cost + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(fund_request_2).expect_success().commit(); let gas_cost_2 = builder.last_exec_gas_cost(); @@ -147,29 +142,24 @@ fn gh_2280_transfer_should_always_cost_the_same_gas() { let mut upgrade_request = make_upgrade_request(); builder.upgrade(&mut upgrade_request); - let fund_request_3 = { - let deploy_hash: [u8; 32] = [77; 32]; - let faucet_args_3 = runtime_args! { - ARG_TARGET => *ACCOUNT_3_ADDR, - ARG_AMOUNT => TOKEN_AMOUNT, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, faucet_args_3) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(*NEW_PROTOCOL_VERSION) - .build() + let deploy_hash: [u8; 32] = [77; 32]; + let faucet_args_3 = runtime_args! { + ARG_TARGET => *ACCOUNT_3_ADDR, + ARG_AMOUNT => TOKEN_AMOUNT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, faucet_args_3) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(fund_request_3).expect_success().commit(); let gas_cost_3 = builder.last_exec_gas_cost(); @@ -206,26 +196,23 @@ fn gh_2280_create_purse_should_always_cost_the_same_gas() { // should be able to pay next time. let payment_amount = Motes::from_gas(gas_cost_1, 1).unwrap(); - let fund_request_2 = { - let deploy_hash: [u8; 32] = [55; 32]; - let create_purse_args_2 = runtime_args! { - ARG_PURSE_NAME => TEST_PURSE_NAME, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, create_purse_args_2) - // + default_create_purse_cost - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let deploy_hash: [u8; 32] = [55; 32]; + let create_purse_args_2 = runtime_args! { + ARG_PURSE_NAME => TEST_PURSE_NAME, + }; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, create_purse_args_2) + // + default_create_purse_cost + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(fund_request_2).expect_success().commit(); let gas_cost_2 = builder.last_exec_gas_cost(); @@ -270,28 +257,23 @@ fn gh_2280_create_purse_should_always_cost_the_same_gas() { .upgrade(&mut upgrade_request) .expect_upgrade_success(); - let fund_request_3 = { - let deploy_hash: [u8; 32] = [77; 32]; - let create_purse_args_3 = runtime_args! { - ARG_PURSE_NAME => TEST_PURSE_NAME, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, create_purse_args_3) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(*NEW_PROTOCOL_VERSION) - .build() + let deploy_hash: [u8; 32] = [77; 32]; + let create_purse_args_3 = runtime_args! { + ARG_PURSE_NAME => TEST_PURSE_NAME, }; + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, create_purse_args_3) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(fund_request_3).expect_success().commit(); let gas_cost_3 = builder.last_exec_gas_cost(); @@ -329,27 +311,24 @@ fn gh_2280_transfer_purse_to_account_should_always_cost_the_same_gas() { // should be able to pay next time. let payment_amount = Motes::from_gas(gas_cost_1, 1).unwrap(); - let fund_request_2 = { - let deploy_hash: [u8; 32] = [55; 32]; - let faucet_args_2 = runtime_args! { - ARG_TARGET => *ACCOUNT_2_ADDR, - ARG_AMOUNT => U512::from(TOKEN_AMOUNT), - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(TRANSFER_PURSE_TO_ACCOUNT_CONTRACT, faucet_args_2) - // + default_create_purse_cost - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let deploy_hash: [u8; 32] = [55; 32]; + let faucet_args_2 = runtime_args! { + ARG_TARGET => *ACCOUNT_2_ADDR, + ARG_AMOUNT => U512::from(TOKEN_AMOUNT), + }; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(TRANSFER_PURSE_TO_ACCOUNT_CONTRACT, faucet_args_2) + // + default_create_purse_cost + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(fund_request_2).expect_success().commit(); let gas_cost_2 = builder.last_exec_gas_cost(); @@ -396,29 +375,24 @@ fn gh_2280_transfer_purse_to_account_should_always_cost_the_same_gas() { .with_chainspec(updated_chainspec) .upgrade(&mut upgrade_request); - let fund_request_3 = { - let deploy_hash: [u8; 32] = [77; 32]; - let faucet_args_3 = runtime_args! { - ARG_TARGET => *ACCOUNT_3_ADDR, - ARG_AMOUNT => U512::from(TOKEN_AMOUNT), - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, faucet_args_3) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(*NEW_PROTOCOL_VERSION) - .build() + let deploy_hash: [u8; 32] = [77; 32]; + let faucet_args_3 = runtime_args! { + ARG_TARGET => *ACCOUNT_3_ADDR, + ARG_AMOUNT => U512::from(TOKEN_AMOUNT), }; + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, faucet_args_3) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(fund_request_3).expect_success().commit(); let gas_cost_3 = builder.last_exec_gas_cost(); @@ -460,26 +434,23 @@ fn gh_2280_stored_transfer_to_account_should_always_cost_the_same_gas() { // should be able to pay next time. let payment_amount = Motes::from_gas(gas_cost_1, 1).unwrap(); - let fund_request_2 = { - let deploy_hash: [u8; 32] = [55; 32]; - let faucet_args_2 = runtime_args! { - ARG_TARGET => *ACCOUNT_2_ADDR, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_stored_session_hash(gh_2280_regression, entry_point, faucet_args_2) - // + default_create_purse_cost - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let deploy_hash: [u8; 32] = [55; 32]; + let faucet_args_2 = runtime_args! { + ARG_TARGET => *ACCOUNT_2_ADDR, + }; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_stored_session_hash(gh_2280_regression, entry_point, faucet_args_2) + // + default_create_purse_cost + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(fund_request_2).expect_success().commit(); let gas_cost_2 = builder.last_exec_gas_cost(); @@ -526,28 +497,23 @@ fn gh_2280_stored_transfer_to_account_should_always_cost_the_same_gas() { .with_chainspec(updated_chainspec) .upgrade(&mut upgrade_request); - let fund_request_3 = { - let deploy_hash: [u8; 32] = [77; 32]; - let faucet_args_3 = runtime_args! { - ARG_TARGET => *ACCOUNT_3_ADDR, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_stored_session_hash(gh_2280_regression, entry_point, faucet_args_3) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(*NEW_PROTOCOL_VERSION) - .build() + let deploy_hash: [u8; 32] = [77; 32]; + let faucet_args_3 = runtime_args! { + ARG_TARGET => *ACCOUNT_3_ADDR, }; + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_stored_session_hash(gh_2280_regression, entry_point, faucet_args_3) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(fund_request_3).expect_success().commit(); let gas_cost_3 = builder.last_exec_gas_cost(); @@ -585,27 +551,24 @@ fn gh_2280_stored_faucet_call_should_cost_the_same() { // should be able to pay next time. let payment_amount = Motes::from_gas(gas_cost_1, 1).unwrap(); - let fund_request_2 = { - let deploy_hash: [u8; 32] = [55; 32]; - let faucet_args_2 = runtime_args! { - ARG_CONTRACT_HASH => gh_2280_regression, - ARG_TARGET => *ACCOUNT_2_ADDR, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, faucet_args_2) - // + default_create_purse_cost - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let deploy_hash: [u8; 32] = [55; 32]; + let faucet_args_2 = runtime_args! { + ARG_CONTRACT_HASH => gh_2280_regression, + ARG_TARGET => *ACCOUNT_2_ADDR, + }; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, faucet_args_2) + // + default_create_purse_cost + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(fund_request_2).expect_success().commit(); let gas_cost_2 = builder.last_exec_gas_cost(); @@ -652,29 +615,24 @@ fn gh_2280_stored_faucet_call_should_cost_the_same() { .with_chainspec(updated_chainspec) .upgrade(&mut upgrade_request); - let fund_request_3 = { - let deploy_hash: [u8; 32] = [77; 32]; - let faucet_args_3 = runtime_args! { - ARG_CONTRACT_HASH => gh_2280_regression, - ARG_TARGET => *ACCOUNT_3_ADDR, - }; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(session_file, faucet_args_3) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new() - .push_deploy(deploy) - .with_protocol_version(*NEW_PROTOCOL_VERSION) - .build() + let deploy_hash: [u8; 32] = [77; 32]; + let faucet_args_3 = runtime_args! { + ARG_CONTRACT_HASH => gh_2280_regression, + ARG_TARGET => *ACCOUNT_3_ADDR, }; + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(session_file, faucet_args_3) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => payment_amount.value() + HOST_FUNCTION_COST_CHANGE + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let fund_request_3 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + builder.exec(fund_request_3).expect_success().commit(); let gas_cost_3 = builder.last_exec_gas_cost(); @@ -695,7 +653,7 @@ struct TestContext { fn setup() -> (LmdbWasmTestBuilder, TestContext) { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let session_args = runtime_args! { mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), @@ -740,8 +698,8 @@ fn make_wasm_config( fn make_upgrade_request() -> ProtocolUpgradeConfig { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build() } diff --git a/execution_engine_testing/tests/src/test/regression/gh_3097.rs b/execution_engine_testing/tests/src/test/regression/gh_3097.rs index ba149277fb..553d73e0ef 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_3097.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_3097.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ @@ -34,7 +33,7 @@ fn should_run_regression() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); diff --git a/execution_engine_testing/tests/src/test/regression/gh_3208.rs b/execution_engine_testing/tests/src/test/regression/gh_3208.rs index bb669c7f83..a06d71aa64 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_3208.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_3208.rs @@ -32,12 +32,12 @@ static ACCOUNTS_WITH_GENESIS_VALIDATORS: Lazy> = Lazy::new(| vec![ GenesisAccount::account( DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), None, ), GenesisAccount::account( DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( Motes::new(*DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE), 15, @@ -133,7 +133,7 @@ fn should_initialize_default_vesting_schedule() { StepRequestBuilder::default() .with_era_end_timestamp_millis(era_end_timestamp_millis) .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .build(), ) .is_success(), @@ -171,8 +171,8 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule() }; let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -197,47 +197,43 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule() builder.exec(add_bid_request).expect_success().commit(); - let withdraw_bid_request_1 = { - let sender = *DEFAULT_PROPOSER_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_WITHDRAW_BID; - let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; - let session_args = runtime_args! { - auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, - }; - - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash([58; 32]) - .build(); + let sender = *DEFAULT_PROPOSER_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_WITHDRAW_BID; + let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = runtime_args! { + auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, + }; - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash([58; 32]) + .build(); + + let withdraw_bid_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + + let sender = *DEFAULT_PROPOSER_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_WITHDRAW_BID; + let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = runtime_args! { + auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, }; - let withdraw_bid_request_2 = { - let sender = *DEFAULT_PROPOSER_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_WITHDRAW_BID; - let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; - let session_args = runtime_args! { - auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, - }; + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash([59; 32]) + .build(); - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash([59; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let withdraw_bid_request_2 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(withdraw_bid_request_1) @@ -258,7 +254,7 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule() StepRequestBuilder::default() .with_era_end_timestamp_millis(era_end_timestamp_millis) .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_run_auction(true) .build(), ) @@ -274,7 +270,7 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule() StepRequestBuilder::default() .with_era_end_timestamp_millis(era_end_timestamp_millis) .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_run_auction(true) .build(), ) @@ -303,8 +299,8 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule_a }; let genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -337,7 +333,7 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule_a StepRequestBuilder::default() .with_era_end_timestamp_millis(era_end_timestamp_millis) .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_run_auction(true) .build(), ) @@ -345,26 +341,24 @@ fn should_immediatelly_unbond_genesis_validator_with_zero_day_vesting_schedule_a "should run step to initialize a schedule" ); - let withdraw_bid_request_1 = { - let sender = *DEFAULT_PROPOSER_ADDR; - let contract_hash = builder.get_auction_contract_hash(); - let entry_point = auction::METHOD_WITHDRAW_BID; - let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; - let session_args = runtime_args! { - auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), - auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, - }; + let sender = *DEFAULT_PROPOSER_ADDR; + let contract_hash = builder.get_auction_contract_hash(); + let entry_point = auction::METHOD_WITHDRAW_BID; + let payment_args = runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let session_args = runtime_args! { + auction::ARG_PUBLIC_KEY => DEFAULT_PROPOSER_PUBLIC_KEY.clone(), + auction::ARG_AMOUNT => *DEFAULT_PROPOSER_ACCOUNT_INITIAL_STAKE, + }; - let deploy = DeployItemBuilder::new() - .with_address(sender) - .with_stored_session_hash(contract_hash, entry_point, session_args) - .with_empty_payment_bytes(payment_args) - .with_authorization_keys(&[sender]) - .with_deploy_hash([58; 32]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(sender) + .with_stored_session_hash(contract_hash, entry_point, session_args) + .with_standard_payment(payment_args) + .with_authorization_keys(&[sender]) + .with_deploy_hash([58; 32]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let withdraw_bid_request_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder .exec(withdraw_bid_request_1) @@ -399,7 +393,7 @@ mod fixture { StepRequestBuilder::default() .with_era_end_timestamp_millis(era_end_timestamp_millis) .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_protocol_version(DEFAULT_PROTOCOL_VERSION) .build(), ); }) diff --git a/execution_engine_testing/tests/src/test/regression/gh_3710.rs b/execution_engine_testing/tests/src/test/regression/gh_3710.rs index b3f9b073dc..5ceced9732 100644 --- a/execution_engine_testing/tests/src/test/regression/gh_3710.rs +++ b/execution_engine_testing/tests/src/test/regression/gh_3710.rs @@ -2,7 +2,7 @@ use std::{collections::BTreeSet, convert::TryInto, iter::FromIterator}; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, StepRequestBuilder, WasmTestBuilder, - DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_PROPOSER_PUBLIC_KEY, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_PROPOSER_PUBLIC_KEY, LOCAL_GENESIS_REQUEST, }; use casper_storage::{ data_access_layer::{PruneRequest, PruneResult}, @@ -189,7 +189,7 @@ fn distribute_rewards( #[test] fn gh_3710_should_produce_era_summary_in_a_step() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); add_validator_and_wait_for_rotation(&mut builder, &DEFAULT_ACCOUNT_PUBLIC_KEY); distribute_rewards(&mut builder, 1, &DEFAULT_ACCOUNT_PUBLIC_KEY, 0.into()); @@ -233,7 +233,7 @@ mod fixture { use casper_engine_test_support::{ ExecuteRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{ runtime_args, @@ -255,7 +255,7 @@ mod fixture { return; } - let genesis_request = PRODUCTION_RUN_GENESIS_REQUEST.clone(); + let genesis_request = LOCAL_GENESIS_REQUEST.clone(); lmdb_fixture::generate_fixture(CALL_STACK_FIXTURE, genesis_request, |builder| { let execute_request = ExecuteRequestBuilder::standard( @@ -281,7 +281,7 @@ mod fixture { return; } - let genesis_request = PRODUCTION_RUN_GENESIS_REQUEST.clone(); + let genesis_request = LOCAL_GENESIS_REQUEST.clone(); lmdb_fixture::generate_fixture(GROUPS_FIXTURE, genesis_request, |builder| { let execute_request = ExecuteRequestBuilder::standard( @@ -304,7 +304,7 @@ mod fixture { return; } // To generate this fixture again you have to re-run this code release-1.4.13. - let genesis_request = PRODUCTION_RUN_GENESIS_REQUEST.clone(); + let genesis_request = LOCAL_GENESIS_REQUEST.clone(); lmdb_fixture::generate_fixture(GH_3710_FIXTURE, genesis_request, |builder| { super::add_validator_and_wait_for_rotation(builder, &DEFAULT_ACCOUNT_PUBLIC_KEY); diff --git a/execution_engine_testing/tests/src/test/regression/gov_116.rs b/execution_engine_testing/tests/src/test/regression/gov_116.rs index 87c0b1b59a..563215ec35 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_116.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_116.rs @@ -4,8 +4,8 @@ use num_traits::Zero; use once_cell::sync::Lazy; use casper_engine_test_support::{ - utils, ChainspecConfig, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNTS, - DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_CHAINSPEC_REGISTRY, + utils, ChainspecConfig, ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, + DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_CHAINSPEC_REGISTRY, DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, DEFAULT_VALIDATOR_SLOTS, MINIMUM_ACCOUNT_CREATION_BALANCE, @@ -13,10 +13,7 @@ use casper_engine_test_support::{ use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ runtime_args, - system::{ - auction::{self, DelegationRate, EraValidators, VESTING_SCHEDULE_LENGTH_MILLIS}, - mint, - }, + system::auction::{self, DelegationRate, EraValidators, VESTING_SCHEDULE_LENGTH_MILLIS}, GenesisAccount, GenesisConfigBuilder, GenesisValidator, Motes, PublicKey, SecretKey, U256, U512, }; @@ -63,9 +60,9 @@ static GENESIS_VALIDATORS: Lazy> = Lazy::new(|| { for (index, public_key) in GENESIS_VALIDATOR_PUBLIC_KEYS.iter().enumerate() { let account = GenesisAccount::account( public_key.clone(), - Motes::new(U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE)), + Motes::new(MINIMUM_ACCOUNT_CREATION_BALANCE), Some(GenesisValidator::new( - Motes::new(U512::from(index + 1) * 1_000), + Motes::new((index + 1) * 1_000), DelegationRate::zero(), )), ); @@ -89,7 +86,7 @@ static LOWEST_STAKE_VALIDATOR: Lazy = Lazy::new(|| { assert_eq!( genesis_account.staked_amount(), - Motes::new(U512::from(MINIMUM_BONDED_AMOUNT)) + Motes::new(MINIMUM_BONDED_AMOUNT) ); genesis_account.public_key() @@ -107,17 +104,13 @@ fn initialize_builder() -> LmdbWasmTestBuilder { let run_genesis_request = utils::create_run_genesis_request(GENESIS_ACCOUNTS.clone()); builder.run_genesis(run_genesis_request); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => PublicKey::System.to_account_hash(), - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, + let fund_request = TransferRequestBuilder::new( + MINIMUM_ACCOUNT_CREATION_BALANCE, + PublicKey::System.to_account_hash(), ) .build(); - builder.exec(fund_request).expect_success().commit(); + builder.transfer_and_commit(fund_request).expect_success(); builder } @@ -258,8 +251,8 @@ fn should_retain_genesis_validator_slot_protection() { .build(); GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ) @@ -268,17 +261,13 @@ fn should_retain_genesis_validator_slot_protection() { let mut builder = LmdbWasmTestBuilder::new_temporary_with_config(chainspec); builder.run_genesis(run_genesis_request); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => PublicKey::System.to_account_hash(), - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, + let fund_request = TransferRequestBuilder::new( + MINIMUM_ACCOUNT_CREATION_BALANCE, + PublicKey::System.to_account_hash(), ) .build(); - builder.exec(fund_request).expect_success().commit(); + builder.transfer_and_commit(fund_request).expect_success(); builder }; diff --git a/execution_engine_testing/tests/src/test/regression/gov_42.rs b/execution_engine_testing/tests/src/test/regression/gov_42.rs index 17690c7344..6da2bdb21d 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_42.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_42.rs @@ -15,11 +15,10 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::MAX_PAYMENT; use casper_types::{runtime_args, Gas, RuntimeArgs}; -use num_traits::Zero; use crate::{ test::regression::test_utils::{ @@ -40,43 +39,36 @@ enum ExecutionPhase { fn run_test_case(input_wasm_bytes: &[u8], expected_error: &str, execution_phase: ExecutionPhase) { let payment_amount = *DEFAULT_PAYMENT; - let (do_minimum_request_builder, expected_error_message) = { - let account_hash = *DEFAULT_ACCOUNT_ADDR; - let session_args = RuntimeArgs::default(); - let deploy_hash = [42; 32]; - - let (deploy_item_builder, expected_error_message) = match execution_phase { - ExecutionPhase::Payment => ( - DeployItemBuilder::new() - .with_payment_bytes( - input_wasm_bytes.to_vec(), - runtime_args! {ARG_AMOUNT => payment_amount,}, - ) - .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args), - expected_error, - ), - ExecutionPhase::Session => ( - DeployItemBuilder::new() - .with_session_bytes(input_wasm_bytes.to_vec(), session_args) - .with_empty_payment_bytes(runtime_args! {ARG_AMOUNT => payment_amount,}), - expected_error, - ), - }; - let deploy = deploy_item_builder - .with_address(account_hash) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ( - ExecuteRequestBuilder::new().push_deploy(deploy), - expected_error_message, - ) + let account_hash = *DEFAULT_ACCOUNT_ADDR; + let session_args = RuntimeArgs::default(); + let deploy_hash = [42; 32]; + + let (deploy_item_builder, expected_error_message) = match execution_phase { + ExecutionPhase::Payment => ( + DeployItemBuilder::new() + .with_payment_bytes( + input_wasm_bytes.to_vec(), + runtime_args! {ARG_AMOUNT => payment_amount,}, + ) + .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args), + expected_error, + ), + ExecutionPhase::Session => ( + DeployItemBuilder::new() + .with_session_bytes(input_wasm_bytes.to_vec(), session_args) + .with_standard_payment(runtime_args! {ARG_AMOUNT => payment_amount,}), + expected_error, + ), }; - let do_minimum_request = do_minimum_request_builder.build(); + let deploy_item = deploy_item_builder + .with_address(account_hash) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + let do_minimum_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -115,7 +107,8 @@ fn run_test_case(input_wasm_bytes: &[u8], expected_error: &str, execution_phase: } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_payment_with_incorrect_wasm_file_invalid_magic_number() { const WASM_BYTES: &[u8] = &[1, 2, 3, 4, 5]; // Correct WASM magic bytes are: 0x00 0x61 0x73 0x6d ("\0asm") let execution_phase = ExecutionPhase::Payment; @@ -124,7 +117,8 @@ fn should_charge_payment_with_incorrect_wasm_file_invalid_magic_number() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_file_invalid_magic_number() { const WASM_BYTES: &[u8] = &[1, 2, 3, 4, 5]; // Correct WASM magic bytes are: 0x00 0x61 0x73 0x6d ("\0asm") let execution_phase = ExecutionPhase::Session; @@ -133,8 +127,9 @@ fn should_charge_session_with_incorrect_wasm_file_invalid_magic_number() { } #[ignore] -#[test] -fn should_charge_payment_with_incorrect_wasm_file_empty_bytes() { +#[allow(unused)] +// #[test] +fn should_fail_to_charge_payment_with_incorrect_wasm_file_empty_bytes() { const WASM_BYTES: &[u8] = &[]; let execution_phase = ExecutionPhase::Payment; let expected_error = "I/O Error: UnexpectedEof"; @@ -142,7 +137,8 @@ fn should_charge_payment_with_incorrect_wasm_file_empty_bytes() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_file_empty_bytes() { const WASM_BYTES: &[u8] = &[]; let execution_phase = ExecutionPhase::Session; @@ -151,7 +147,8 @@ fn should_charge_session_with_incorrect_wasm_file_empty_bytes() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_payment_with_incorrect_wasm_correct_magic_number_incomplete_module() { const WASM_BYTES: &[u8] = &[ 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, 0x02, 0x7F, 0x7F, @@ -171,7 +168,8 @@ fn should_charge_payment_with_incorrect_wasm_correct_magic_number_incomplete_mod } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_correct_magic_number_incomplete_module() { const WASM_BYTES: &[u8] = &[ 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, 0x02, 0x7F, 0x7F, @@ -191,7 +189,8 @@ fn should_charge_session_with_incorrect_wasm_correct_magic_number_incomplete_mod } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_payment_with_incorrect_wasm_gas_counter_overflow() { let wasm_bytes = make_gas_counter_overflow(); let execution_phase = ExecutionPhase::Payment; @@ -200,7 +199,8 @@ fn should_charge_payment_with_incorrect_wasm_gas_counter_overflow() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_gas_counter_overflow() { let wasm_bytes = make_gas_counter_overflow(); let execution_phase = ExecutionPhase::Session; @@ -209,7 +209,8 @@ fn should_charge_session_with_incorrect_wasm_gas_counter_overflow() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_payment_with_incorrect_wasm_no_memory_section() { let wasm_bytes = make_module_without_memory_section(); let execution_phase = ExecutionPhase::Payment; @@ -218,7 +219,8 @@ fn should_charge_payment_with_incorrect_wasm_no_memory_section() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_no_memory_section() { let wasm_bytes = make_module_without_memory_section(); let execution_phase = ExecutionPhase::Session; @@ -227,19 +229,21 @@ fn should_charge_session_with_incorrect_wasm_no_memory_section() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_payment_with_incorrect_wasm_start_section() { let wasm_bytes = make_module_with_start_section(); let execution_phase = ExecutionPhase::Payment; - let expected_error = "Unsupported WASM start"; + let expected_error = "Unsupported Wasm start"; run_test_case(&wasm_bytes, expected_error, execution_phase) } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_session_with_incorrect_wasm_start_section() { let wasm_bytes = make_module_with_start_section(); let execution_phase = ExecutionPhase::Session; - let expected_error = "Unsupported WASM start"; + let expected_error = "Unsupported Wasm start"; run_test_case(&wasm_bytes, expected_error, execution_phase) } diff --git a/execution_engine_testing/tests/src/test/regression/gov_427.rs b/execution_engine_testing/tests/src/test/regression/gov_427.rs index 9534a91e0b..ac33239243 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_427.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_427.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_WASM_CONFIG, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{addressable_entity::DEFAULT_ENTRY_POINT_NAME, RuntimeArgs}; @@ -80,7 +80,7 @@ fn too_many_locals_should_exceed_stack_height() { ); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let success_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/regression/gov_74.rs b/execution_engine_testing/tests/src/test/regression/gov_74.rs index 0336697292..d45d2a8bdc 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_74.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_74.rs @@ -1,8 +1,6 @@ -use once_cell::sync::Lazy; - use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PROTOCOL_VERSION, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{ engine_state::Error, @@ -17,19 +15,16 @@ const ARITY_INTERPRETER_LIMIT: usize = DEFAULT_MAX_PARAMETER_COUNT as usize; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); const I32_WAT_TYPE: &str = "i64"; const NEW_WASM_STACK_HEIGHT: u32 = 16; - -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); fn initialize_builder() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder } @@ -111,8 +106,8 @@ fn should_observe_stack_height_limit() { builder.with_chainspec(updated_chainspec); let mut upgrade_request = UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build(); @@ -132,7 +127,6 @@ fn should_observe_stack_height_limit() { module_bytes, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build() }; @@ -156,7 +150,6 @@ fn should_observe_stack_height_limit() { module_bytes, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build() }; diff --git a/execution_engine_testing/tests/src/test/regression/gov_89_regression.rs b/execution_engine_testing/tests/src/test/regression/gov_89_regression.rs index 298255662a..e5a9c40aac 100644 --- a/execution_engine_testing/tests/src/test/regression/gov_89_regression.rs +++ b/execution_engine_testing/tests/src/test/regression/gov_89_regression.rs @@ -41,17 +41,17 @@ fn initialize_builder() -> LmdbWasmTestBuilder { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PUBLIC_KEY.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PUBLIC_KEY.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs b/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs index 16d468855e..b594619e28 100644 --- a/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs +++ b/execution_engine_testing/tests/src/test/regression/host_function_metrics_size_and_gas_cost.rs @@ -1,13 +1,10 @@ use std::convert::TryInto; use casper_engine_test_support::{ - utils, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, -}; -use casper_execution_engine::{ - engine_state::{self, ExecuteRequest}, - execution::ExecError, + utils, DeployItemBuilder, ExecuteRequest, ExecuteRequestBuilder, LmdbWasmTestBuilder, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; +use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{ account::{AccountHash, ACCOUNT_HASH_LENGTH}, bytesrepr::Bytes, @@ -49,7 +46,7 @@ const TRANSFER_FROM_MAIN_PURSE_AMOUNT: u64 = 2_000_000_u64; #[ignore] #[test] fn host_function_metrics_has_acceptable_size() { - let size = utils::read_wasm_file_bytes(CONTRACT_HOST_FUNCTION_METRICS).len(); + let size = utils::read_wasm_file(CONTRACT_HOST_FUNCTION_METRICS).len(); assert!( size <= HOST_FUNCTION_METRICS_MAX_SIZE, "Performance regression: contract host-function-metrics became {} bytes long; up to {} bytes long would be acceptable.", @@ -88,25 +85,21 @@ fn host_function_metrics_has_acceptable_gas_cost() { random_bytes }; - let exec_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(ACCOUNT0_ADDR) - .with_deploy_hash([55; 32]) - .with_session_code( - CONTRACT_HOST_FUNCTION_METRICS, - runtime_args! { - ARG_SEED => seed, - ARG_OTHERS => (Bytes::from(random_bytes), ACCOUNT0_ADDR, ACCOUNT1_ADDR), - ARG_AMOUNT => TRANSFER_FROM_MAIN_PURSE_AMOUNT, - }, - ) - .with_empty_payment_bytes( - runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT }, - ) - .with_authorization_keys(&[ACCOUNT0_ADDR]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT0_ADDR) + .with_deploy_hash([55; 32]) + .with_session_code( + CONTRACT_HOST_FUNCTION_METRICS, + runtime_args! { + ARG_SEED => seed, + ARG_OTHERS => (Bytes::from(random_bytes), ACCOUNT0_ADDR, ACCOUNT1_ADDR), + ARG_AMOUNT => TRANSFER_FROM_MAIN_PURSE_AMOUNT, + }, + ) + .with_standard_payment(runtime_args! { standard_payment::ARG_AMOUNT => *DEFAULT_PAYMENT }) + .with_authorization_keys(&[ACCOUNT0_ADDR]) + .build(); + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request); @@ -133,7 +126,7 @@ fn host_function_metrics_has_acceptable_gas_cost() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(create_account_exec_request(ACCOUNT0_ADDR)) .expect_success() .commit() diff --git a/execution_engine_testing/tests/src/test/regression/regression_20210707.rs b/execution_engine_testing/tests/src/test/regression/regression_20210707.rs index 62f1b0585b..d3cdb68ed2 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20210707.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20210707.rs @@ -1,18 +1,16 @@ +use once_cell::sync::Lazy; + use casper_engine_test_support::{ - DeployItemBuilder, EntityWithNamedKeys, ExecuteRequestBuilder, LmdbWasmTestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, + DeployItemBuilder, EntityWithNamedKeys, ExecuteRequest, ExecuteRequestBuilder, + LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; -use casper_execution_engine::{ - engine_state::{Error as CoreError, ExecuteRequest}, - execution::ExecError, -}; -use casper_storage::system::transfer::TransferError; +use casper_execution_engine::{engine_state::Error as CoreError, execution::ExecError}; +use casper_storage::{data_access_layer::TransferRequest, system::transfer::TransferError}; use casper_types::{ account::AccountHash, runtime_args, system::mint, AccessRights, AddressableEntityHash, PublicKey, RuntimeArgs, SecretKey, URef, U512, }; -use once_cell::sync::Lazy; use crate::wasm_utils; @@ -55,16 +53,10 @@ fn setup_regression_contract() -> ExecuteRequest { .build() } -fn transfer(sender: AccountHash, target: AccountHash, amount: u64) -> ExecuteRequest { - ExecuteRequestBuilder::transfer( - sender, - runtime_args! { - mint::ARG_TARGET => target, - mint::ARG_AMOUNT => U512::from(amount), - mint::ARG_ID => >::None, - }, - ) - .build() +fn transfer(sender: AccountHash, target: AccountHash, amount: u64) -> TransferRequest { + TransferRequestBuilder::new(amount, target) + .with_initiator(sender) + .build() } fn get_account_entity_hash(entity: &EntityWithNamedKeys) -> AddressableEntityHash { @@ -92,7 +84,7 @@ fn assert_forged_uref_error(error: CoreError, forged_uref: URef) { fn should_transfer_funds_from_contract_to_new_account() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -103,7 +95,7 @@ fn should_transfer_funds_from_contract_to_new_account() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request).commit().expect_success(); + builder.transfer_and_commit(fund_request).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -132,7 +124,7 @@ fn should_transfer_funds_from_contract_to_new_account() { fn should_transfer_funds_from_contract_to_existing_account() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -149,8 +141,8 @@ fn should_transfer_funds_from_contract_to_existing_account() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); - builder.exec(fund_request_2).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); + builder.transfer_and_commit(fund_request_2).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -177,7 +169,7 @@ fn should_transfer_funds_from_contract_to_existing_account() { fn should_not_transfer_funds_from_forged_purse_to_account_native_transfer() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -188,24 +180,16 @@ fn should_not_transfer_funds_from_forged_purse_to_account_native_transfer() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request).commit().expect_success(); + builder.transfer_and_commit(fund_request).expect_success(); let take_from = builder.get_expected_addressable_entity_by_account_hash(*ALICE_ADDR); let alice_main_purse = take_from.main_purse(); - let transfer_request = { - let id: Option = None; - let transfer_args = runtime_args! { - mint::ARG_SOURCE => alice_main_purse, - mint::ARG_TARGET => *BOB_ADDR, - mint::ARG_AMOUNT => U512::from(700_000_000_000u64), - mint::ARG_ID => id, - }; + let transfer_request = TransferRequestBuilder::new(700_000_000_000_u64, *BOB_ADDR) + .with_source(alice_main_purse) + .build(); - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build() - }; - - builder.exec(transfer_request).commit(); + builder.transfer_and_commit(transfer_request); let error = builder.get_error().expect("should have error"); @@ -222,7 +206,7 @@ fn should_not_transfer_funds_from_forged_purse_to_account_native_transfer() { fn should_not_transfer_funds_from_forged_purse_to_owned_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -239,8 +223,8 @@ fn should_not_transfer_funds_from_forged_purse_to_owned_purse() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); - builder.exec(fund_request_2).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); + builder.transfer_and_commit(fund_request_2).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -276,7 +260,7 @@ fn should_not_transfer_funds_from_forged_purse_to_owned_purse() { fn should_not_transfer_funds_into_bob_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -287,7 +271,7 @@ fn should_not_transfer_funds_into_bob_purse() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -321,7 +305,7 @@ fn should_not_transfer_funds_into_bob_purse() { fn should_not_transfer_from_hardcoded_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -332,7 +316,7 @@ fn should_not_transfer_from_hardcoded_purse() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -358,11 +342,12 @@ fn should_not_transfer_from_hardcoded_purse() { } #[ignore] -#[test] +#[allow(unused)] +//#[test] fn should_not_refund_to_bob_and_charge_alice() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -379,8 +364,8 @@ fn should_not_refund_to_bob_and_charge_alice() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); - builder.exec(fund_request_2).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); + builder.transfer_and_commit(fund_request_2).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -391,22 +376,19 @@ fn should_not_refund_to_bob_and_charge_alice() { let contract_hash = get_account_entity_hash(&account); - let call_request = { - let args = runtime_args! { - ARG_SOURCE => bob_main_purse, - ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - // Just do nothing if ever we'd get into session execution - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_stored_payment_hash(contract_hash, METHOD_STORED_PAYMENT, args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([77; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + ARG_SOURCE => bob_main_purse, + ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_stored_payment_hash(contract_hash, METHOD_STORED_PAYMENT, args) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([77; 32]) + .build(); + + let call_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(call_request).commit(); @@ -416,11 +398,12 @@ fn should_not_refund_to_bob_and_charge_alice() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_charge_alice_for_execution() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -437,8 +420,8 @@ fn should_not_charge_alice_for_execution() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); - builder.exec(fund_request_2).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); + builder.transfer_and_commit(fund_request_2).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -449,22 +432,20 @@ fn should_not_charge_alice_for_execution() { let contract_hash = get_account_entity_hash(&account); - let call_request = { - let args = runtime_args! { - ARG_SOURCE => bob_main_purse, - ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - // Just do nothing if ever we'd get into session execution - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_stored_payment_hash(contract_hash, METHOD_STORED_PAYMENT, args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([77; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + ARG_SOURCE => bob_main_purse, + ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + // Just do nothing if ever we'd get into session execution + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_stored_payment_hash(contract_hash, METHOD_STORED_PAYMENT, args) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([77; 32]) + .build(); + + let call_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(call_request).commit(); @@ -474,11 +455,12 @@ fn should_not_charge_alice_for_execution() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_not_charge_for_execution_from_hardcoded_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let store_request = setup_regression_contract(); @@ -495,8 +477,8 @@ fn should_not_charge_for_execution_from_hardcoded_purse() { ); builder.exec(store_request).commit().expect_success(); - builder.exec(fund_request_1).commit().expect_success(); - builder.exec(fund_request_2).commit().expect_success(); + builder.transfer_and_commit(fund_request_1).expect_success(); + builder.transfer_and_commit(fund_request_2).expect_success(); let account = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -504,21 +486,19 @@ fn should_not_charge_for_execution_from_hardcoded_purse() { let contract_hash = get_account_entity_hash(&account); - let call_request = { - let args = runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT, - }; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - // Just do nothing if ever we'd get into session execution - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_stored_payment_hash(contract_hash, METHOD_HARDCODED_PAYMENT, args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([77; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() + let args = runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT, }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + // Just do nothing if ever we'd get into session execution + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_stored_payment_hash(contract_hash, METHOD_HARDCODED_PAYMENT, args) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([77; 32]) + .build(); + + let call_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(call_request).commit(); diff --git a/execution_engine_testing/tests/src/test/regression/regression_20210831.rs b/execution_engine_testing/tests/src/test/regression/regression_20210831.rs index 12b9d9d132..b3166c2a92 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20210831.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20210831.rs @@ -1,8 +1,8 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + DEFAULT_ACCOUNT_PUBLIC_KEY, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{ engine_state::{engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, Error as CoreError}, @@ -11,10 +11,7 @@ use casper_execution_engine::{ use casper_types::{ account::AccountHash, runtime_args, - system::{ - auction::{self, BidsExt, DelegationRate}, - mint, - }, + system::auction::{self, BidsExt, DelegationRate}, ApiError, PublicKey, RuntimeArgs, SecretKey, U512, }; @@ -47,59 +44,39 @@ static DELEGATE_AMOUNT: Lazy = Lazy::new(|| U512::from(500_000)); fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let id: Option = None; - - let transfer_args_1 = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => id, - }; + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_request_1 = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args_1).build(); - - builder.exec(transfer_request_1).expect_success().commit(); + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR).build(); - let transfer_args_2 = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => id, - }; + builder + .transfer_and_commit(transfer_request_1) + .expect_success(); let transfer_request_2 = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args_2).build(); + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_2_ADDR).build(); - builder.exec(transfer_request_2).expect_success().commit(); + builder + .transfer_and_commit(transfer_request_2) + .expect_success(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); - - let id: Option = None; - - let transfer_args_1 = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => id, - }; + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_request_1 = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args_1).build(); + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR).build(); - builder.exec(transfer_request_1).expect_success().commit(); - - let transfer_args_2 = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => id, - }; + builder + .transfer_and_commit(transfer_request_1) + .expect_success(); let transfer_request_2 = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args_2).build(); + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_2_ADDR).build(); - builder.exec(transfer_request_2).expect_success().commit(); + builder + .transfer_and_commit(transfer_request_2) + .expect_success(); let install_request_1 = ExecuteRequestBuilder::standard( *ACCOUNT_2_ADDR, @@ -467,7 +444,7 @@ fn regression_20210831_should_fail_to_activate_bid() { let sender = *ACCOUNT_2_ADDR; let activate_bid_args = runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), + auction::ARG_VALIDATOR => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(), }; let activate_bid_request_1 = ExecuteRequestBuilder::contract_call_by_hash( diff --git a/execution_engine_testing/tests/src/test/regression/regression_20210924.rs b/execution_engine_testing/tests/src/test/regression/regression_20210924.rs index 8e90e4d358..7adc31464a 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20210924.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20210924.rs @@ -1,8 +1,6 @@ -use num_traits::Zero; - use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::{Error as CoreError, MAX_PAYMENT}; use casper_types::{runtime_args, Gas, RuntimeArgs, DEFAULT_NOP_COST, U512}; @@ -12,32 +10,30 @@ use crate::wasm_utils; const ARG_AMOUNT: &str = "amount"; #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_minimum_for_do_nothing_session() { let minimum_deploy_payment = U512::from(0); - let do_nothing_request = { - let account_hash = *DEFAULT_ACCOUNT_ADDR; - let session_args = RuntimeArgs::default(); - let deploy_hash = [42; 32]; + let account_hash = *DEFAULT_ACCOUNT_ADDR; + let session_args = RuntimeArgs::default(); + let deploy_hash = [42; 32]; - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => minimum_deploy_payment, - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => minimum_deploy_payment, + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let do_nothing_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -70,32 +66,30 @@ fn should_charge_minimum_for_do_nothing_session() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_execute_do_minimum_session() { let minimum_deploy_payment = U512::from(DEFAULT_NOP_COST); - let do_minimum_request = { - let account_hash = *DEFAULT_ACCOUNT_ADDR; - let session_args = RuntimeArgs::default(); - let deploy_hash = [42; 32]; + let account_hash = *DEFAULT_ACCOUNT_ADDR; + let session_args = RuntimeArgs::default(); + let deploy_hash = [42; 32]; - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => minimum_deploy_payment, - }) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_bytes(wasm_utils::do_minimum_bytes(), session_args) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => minimum_deploy_payment, + }) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let do_minimum_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -124,35 +118,33 @@ fn should_execute_do_minimum_session() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_charge_minimum_for_do_nothing_payment() { let minimum_deploy_payment = U512::from(0); - let do_nothing_request = { - let account_hash = *DEFAULT_ACCOUNT_ADDR; - let session_args = RuntimeArgs::default(); - let deploy_hash = [42; 32]; - - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args) - .with_payment_bytes( - wasm_utils::do_nothing_bytes(), - runtime_args! { - ARG_AMOUNT => minimum_deploy_payment, - }, - ) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy) - } - .build(); + let account_hash = *DEFAULT_ACCOUNT_ADDR; + let session_args = RuntimeArgs::default(); + let deploy_hash = [42; 32]; + + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_bytes(wasm_utils::do_nothing_bytes(), session_args) + .with_payment_bytes( + wasm_utils::do_nothing_bytes(), + runtime_args! { + ARG_AMOUNT => minimum_deploy_payment, + }, + ) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); + + let do_nothing_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) diff --git a/execution_engine_testing/tests/src/test/regression/regression_20211110.rs b/execution_engine_testing/tests/src/test/regression/regression_20211110.rs index dcf7721c5c..cfe80c4d9d 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20211110.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20211110.rs @@ -1,13 +1,10 @@ use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, + LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error as CoreError, execution::ExecError}; use casper_types::{ - account::AccountHash, - runtime_args, - system::{mint, standard_payment}, - AddressableEntityHash, Key, U512, + account::AccountHash, runtime_args, system::standard_payment, AddressableEntityHash, Key, U512, }; const RECURSE_ENTRYPOINT: &str = "recurse"; @@ -25,35 +22,27 @@ fn regression_20211110() { let mut funds: u64 = STARTING_BALANCE; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(funds), - mint::ARG_ID => Option::::None - }, - ) - .build(); + let transfer_request = TransferRequestBuilder::new(funds, ACCOUNT_1_ADDR).build(); - let install_request = { - let session_args = runtime_args! {}; - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => U512::from(INSTALL_COST) - }; - let deploy_item = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_empty_payment_bytes(payment_args) - .with_session_code(REGRESSION_20211110_CONTRACT, session_args) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() + let session_args = runtime_args! {}; + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => U512::from(INSTALL_COST) }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_standard_payment(payment_args) + .with_session_code(REGRESSION_20211110_CONTRACT, session_args) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let install_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - builder.exec(transfer_request).expect_success().commit(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); builder.exec(install_request).expect_success().commit(); funds = funds.checked_sub(INSTALL_COST).unwrap(); @@ -69,22 +58,20 @@ fn regression_20211110() { _ => panic!("Couldn't find regression contract."), }; - let recurse_request = { - let payment_args = runtime_args! { - standard_payment::ARG_AMOUNT => U512::from(funds), - }; - let session_args = runtime_args! { - ARG_TARGET => contract_hash - }; - let deploy_item = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_empty_payment_bytes(payment_args) - .with_stored_session_hash(contract_hash, RECURSE_ENTRYPOINT, session_args) - .with_authorization_keys(&[ACCOUNT_1_ADDR]) - .with_deploy_hash([43; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() + let payment_args = runtime_args! { + standard_payment::ARG_AMOUNT => U512::from(funds), + }; + let session_args = runtime_args! { + ARG_TARGET => contract_hash }; + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_standard_payment(payment_args) + .with_stored_session_hash(contract_hash, RECURSE_ENTRYPOINT, session_args) + .with_authorization_keys(&[ACCOUNT_1_ADDR]) + .with_deploy_hash([43; 32]) + .build(); + let recurse_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(recurse_request).expect_failure(); diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220119.rs b/execution_engine_testing/tests/src/test/regression/regression_20220119.rs index 2fe3ba41eb..ee48e68bb1 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220119.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220119.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::RuntimeArgs; @@ -10,7 +9,7 @@ const REGRESSION_20220119_CONTRACT: &str = "regression_20220119.wasm"; #[test] fn should_create_purse() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220204.rs b/execution_engine_testing/tests/src/test/regression/regression_20220204.rs index aac76090b1..02cb831d74 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220204.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220204.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{runtime_args, AccessRights, RuntimeArgs}; @@ -247,7 +246,7 @@ fn regression_20220204_as_contract_by_hash_attenuated() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, REGRESSION_20220204_CONTRACT, diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220207.rs b/execution_engine_testing/tests/src/test/regression/regression_20220207.rs index 0a943ce6c9..7a1c49ac02 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220207.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220207.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{account::AccountHash, runtime_args, system::mint, ApiError, U512}; @@ -17,7 +16,7 @@ const UNAPPROVED_SPENDING_AMOUNT_ERR: Error = Error::Exec(ExecError::Revert(ApiE #[test] fn should_not_transfer_above_approved_limit() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let args = runtime_args! { mint::ARG_AMOUNT => U512::from(1000u64), // What we approved. @@ -38,7 +37,7 @@ fn should_not_transfer_above_approved_limit() { #[test] fn should_transfer_within_approved_limit() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let args = runtime_args! { mint::ARG_AMOUNT => U512::from(1000u64), @@ -57,7 +56,7 @@ fn should_transfer_within_approved_limit() { #[test] fn should_fail_without_amount_arg() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let args = runtime_args! { // If `amount` arg is absent, host assumes that limit is 0. diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220208.rs b/execution_engine_testing/tests/src/test/regression/regression_20220208.rs index f64ab14d10..f919ed508a 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220208.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220208.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{account::AccountHash, runtime_args, system::mint, ApiError, U512}; @@ -18,7 +17,7 @@ const UNAPPROVED_SPENDING_AMOUNT_ERR: Error = Error::Exec(ExecError::Revert(ApiE #[test] fn should_transfer_within_approved_limit_multiple_transfers() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let part_1 = U512::from(100u64); let part_2 = U512::from(100u64); @@ -42,7 +41,7 @@ fn should_transfer_within_approved_limit_multiple_transfers() { #[test] fn should_not_transfer_above_approved_limit_multiple_transfers() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let part_1 = U512::from(100u64); let part_2 = U512::from(100u64); diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220211.rs b/execution_engine_testing/tests/src/test/regression/regression_20220211.rs index 755fec5bdd..7611764a08 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220211.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220211.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{runtime_args, AccessRights, RuntimeArgs, URef}; @@ -33,7 +32,7 @@ fn regression_20220211_ret_as_session() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, REGRESSION_20220211_CONTRACT, diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220217.rs b/execution_engine_testing/tests/src/test/regression/regression_20220217.rs index a089f248dd..d5410cbcce 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220217.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220217.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{account::AccountHash, runtime_args, system::mint, AccessRights, URef, U512}; @@ -256,17 +256,10 @@ fn regression_20220217_should_not_transfer_funds_on_unrelated_purses() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let fund_account_1_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_account_1_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR).build(); let fund_purse_1_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, TRANSFER_TO_NAMED_PURSE_CONTRACT, @@ -296,9 +289,8 @@ fn setup() -> LmdbWasmTestBuilder { .build(); builder - .exec(fund_account_1_request) - .expect_success() - .commit(); + .transfer_and_commit(fund_account_1_request) + .expect_success(); builder.exec(fund_purse_1_request).expect_success().commit(); builder.exec(fund_purse_2_request).expect_success().commit(); builder.exec(fund_purse_3_request).expect_success().commit(); @@ -399,7 +391,7 @@ fn mint_by_hash_transfer_should_fail_because_lack_of_target_uref_access() { // TODO create two named purses and verify we can pass source and target known non-main purses let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220221.rs b/execution_engine_testing/tests/src/test/regression/regression_20220221.rs index 0faeac8a00..b49012ce78 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220221.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220221.rs @@ -1,18 +1,13 @@ -use once_cell::sync::Lazy; - use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, StepRequestBuilder, UpgradeRequestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_AUCTION_DELAY, DEFAULT_GENESIS_TIMESTAMP_MILLIS, - DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, TIMESTAMP_MILLIS_INCREMENT, + ExecuteRequestBuilder, LmdbWasmTestBuilder, StepRequestBuilder, TransferRequestBuilder, + UpgradeRequestBuilder, DEFAULT_AUCTION_DELAY, DEFAULT_GENESIS_TIMESTAMP_MILLIS, + DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, TIMESTAMP_MILLIS_INCREMENT, }; use casper_execution_engine::engine_state::DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT; use casper_types::{ runtime_args, - system::{ - auction::{self, DelegationRate, INITIAL_ERA_ID}, - mint, - }, + system::auction::{self, DelegationRate, INITIAL_ERA_ID}, EraId, ProtocolVersion, PublicKey, SecretKey, U256, U512, }; @@ -20,14 +15,12 @@ const VALIDATOR_STAKE: u64 = 1_000_000_000; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); fn generate_secret_keys() -> impl Iterator { (1u64..).map(|i| { @@ -50,47 +43,37 @@ fn regression_20220221_should_distribute_to_many_validators() { let mut public_keys = generate_public_keys(); - let fund_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => PublicKey::System, - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - mint::ARG_ID => >::None, - }, - ) - .build(); + let fund_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, PublicKey::System).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut upgrade_request = UpgradeRequestBuilder::default() .with_new_validator_slots(DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT + 1) .with_pre_state_hash(builder.get_post_state_hash()) - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build(); builder.upgrade(&mut upgrade_request); - builder.exec(fund_request).expect_success().commit(); + builder.transfer_and_commit(fund_request).expect_success(); // Add validators for _ in 0..DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT { let public_key = public_keys.next().unwrap(); - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => public_key.to_account_hash(), - mint::ARG_AMOUNT => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE / 10), - mint::ARG_ID => >::None, - }, + let transfer_request = TransferRequestBuilder::new( + MINIMUM_ACCOUNT_CREATION_BALANCE / 10, + public_key.to_account_hash(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); - builder.exec(transfer_request).commit().expect_success(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let delegation_rate: DelegationRate = 10; @@ -106,7 +89,6 @@ fn regression_20220221_should_distribute_to_many_validators() { auction::METHOD_ADD_BID, session_args, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(execute_request).expect_success().commit(); @@ -132,7 +114,7 @@ fn regression_20220221_should_distribute_to_many_validators() { let step_request = StepRequestBuilder::new() .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(*NEW_PROTOCOL_VERSION) + .with_protocol_version(NEW_PROTOCOL_VERSION) // Next era id is used for returning future era validators, which we don't need to inspect // in this test. .with_next_era_id(era_id) diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220222.rs b/execution_engine_testing/tests/src/test/regression/regression_20220222.rs index 9a43b33a29..696b6bac89 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220222.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220222.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, DEFAULT_ACCOUNT_ADDR, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{account::AccountHash, runtime_args, U512}; @@ -11,19 +11,14 @@ const ALICE_ADDR: AccountHash = AccountHash::new([42; 32]); #[test] fn regression_20220222_escalate() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let transfer_request = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - "target" => ALICE_ADDR, - "amount" => U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE), - "id" => >::None, - }, - ) - .build(); + let transfer_request = + TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ALICE_ADDR).build(); - builder.exec(transfer_request).commit().expect_success(); + builder + .transfer_and_commit(transfer_request) + .expect_success(); let alice = builder .get_entity_by_account_hash(ALICE_ADDR) diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220223.rs b/execution_engine_testing/tests/src/test/regression/regression_20220223.rs index 526d217977..9f443ad844 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220223.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220223.rs @@ -3,7 +3,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{ engine_state, engine_state::engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, @@ -278,7 +278,7 @@ fn should_fail_to_mint_transfer_over_the_limit() { fn setup() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let validator_1_fund_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, CONTRACT_TRANSFER_TO_ACCOUNT, diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220224.rs b/execution_engine_testing/tests/src/test/regression/regression_20220224.rs index 599df72360..f6e6e34b12 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220224.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220224.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{runtime_args, system::mint, ApiError, RuntimeArgs}; @@ -12,26 +12,24 @@ const CONTRACT_REVERT: &str = "revert.wasm"; #[test] fn should_not_transfer_above_approved_limit_in_payment_code() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = { - let account_hash = *DEFAULT_ACCOUNT_ADDR; - let deploy_hash: [u8; 32] = [42; 32]; - let payment_args = runtime_args! { - "amount" => *DEFAULT_PAYMENT, - }; - let session_args = RuntimeArgs::default(); + let account_hash = *DEFAULT_ACCOUNT_ADDR; + let deploy_hash: [u8; 32] = [42; 32]; + let payment_args = runtime_args! { + "amount" => *DEFAULT_PAYMENT, + }; + let session_args = RuntimeArgs::default(); - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_session_code(CONTRACT_REVERT, session_args) - .with_payment_code(CONTRACT_REGRESSION_PAYMENT, payment_args) - .with_authorization_keys(&[account_hash]) - .with_deploy_hash(deploy_hash) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_session_code(CONTRACT_REVERT, session_args) + .with_payment_code(CONTRACT_REGRESSION_PAYMENT, payment_args) + .with_authorization_keys(&[account_hash]) + .with_deploy_hash(deploy_hash) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(exec_request).expect_failure().commit(); diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220303.rs b/execution_engine_testing/tests/src/test/regression/regression_20220303.rs index 0431eb1268..60aaef2892 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220303.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220303.rs @@ -12,7 +12,7 @@ use casper_types::{ }; use rand::Rng; -use crate::lmdb_fixture::{self, CONTRACT_REGISTRY_SPECIAL_ADDRESS}; +use crate::lmdb_fixture::{self, ENTRY_REGISTRY_SPECIAL_ADDRESS}; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); @@ -45,8 +45,8 @@ fn test_upgrade(major_bump: u32, minor_bump: u32, patch_bump: u32, upgrade_entri lmdb_fixture::builder_from_global_state_fixture(lmdb_fixture::RELEASE_1_3_1); let mint_contract_hash = { let stored_value: StoredValue = builder - .query(None, CONTRACT_REGISTRY_SPECIAL_ADDRESS, &[]) - .expect("should query system contract registry"); + .query(None, ENTRY_REGISTRY_SPECIAL_ADDRESS, &[]) + .expect("should query system entity registry"); let cl_value = stored_value .as_cl_value() .cloned() diff --git a/execution_engine_testing/tests/src/test/regression/regression_20220727.rs b/execution_engine_testing/tests/src/test/regression/regression_20220727.rs index 211a82c260..283cb6e9c0 100644 --- a/execution_engine_testing/tests/src/test/regression/regression_20220727.rs +++ b/execution_engine_testing/tests/src/test/regression/regression_20220727.rs @@ -6,8 +6,7 @@ use casper_wasm::{ }; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{ engine_state, @@ -56,7 +55,7 @@ fn make_oom_payload(initial: u32, maximum: Option) -> Vec { #[test] fn should_not_oom() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let initial_size_exceeded = vec![OOM_INIT, FAILURE_ONE_ABOVE_LIMIT]; @@ -115,7 +114,7 @@ fn should_not_oom() { #[test] fn should_pass_table_validation() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let passing_test_cases = vec![ALLOWED_NO_MAX, ALLOWED_LIMITS]; @@ -189,7 +188,7 @@ fn test_element_section( // ) let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut wat = String::new(); @@ -246,7 +245,7 @@ fn test_element_section( #[test] fn should_not_allow_more_than_one_table() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // wabt::wat2wasm doesn't allow multiple tables so we'll go with a builder @@ -379,7 +378,7 @@ fn should_allow_large_br_table() { .expect("should create module bytes"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -398,7 +397,7 @@ fn should_not_allow_large_br_table() { make_arbitrary_br_table(FAILING_BR_TABLE_SIZE).expect("should create module bytes"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -468,7 +467,7 @@ fn should_allow_multiple_globals() { make_arbitrary_global(DEFAULT_MAX_GLOBALS as usize).expect("should make arbitrary global"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -487,7 +486,7 @@ fn should_not_allow_too_many_globals() { make_arbitrary_global(FAILING_GLOBALS_SIZE).expect("should make arbitrary global"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -519,7 +518,7 @@ fn should_verify_max_param_count() { .expect("should create wasm bytes"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -534,7 +533,7 @@ fn should_verify_max_param_count() { wasm_utils::make_n_arg_call_bytes(100, "i32").expect("should create wasm bytes"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -553,7 +552,7 @@ fn should_not_allow_too_many_params() { .expect("should create wasm bytes"); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -589,7 +588,7 @@ fn should_not_allow_to_import_gas_function() { .unwrap(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, @@ -724,7 +723,7 @@ fn should_not_set_non_existing_global_above_declared_range() { fn test_non_existing_global(module_wat: &str, index: u32) { let module_bytes = wat::parse_str(module_wat).unwrap(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, module_bytes, diff --git a/execution_engine_testing/tests/src/test/regression/slow_input.rs b/execution_engine_testing/tests/src/test/regression/slow_input.rs index 15fdbff754..e8ef51f76b 100644 --- a/execution_engine_testing/tests/src/test/regression/slow_input.rs +++ b/execution_engine_testing/tests/src/test/regression/slow_input.rs @@ -1,8 +1,7 @@ use std::mem; use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ @@ -65,7 +64,7 @@ const SLOW_INPUT: &str = r#"(module fn should_measure_slow_input() { let module_bytes = wat::parse_str(SLOW_INPUT).unwrap(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, module_bytes, @@ -83,7 +82,7 @@ fn should_measure_slow_input_with_infinite_br_loop() { let module_bytes = make_cpu_burner_br(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, module_bytes, @@ -100,7 +99,7 @@ fn should_measure_slow_input_with_infinite_br_loop() { fn should_measure_br_if_cpu_burner_with_br_if_iterations() { let module_bytes = cpu_burner_br_if(u32::MAX as i64); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, module_bytes, @@ -118,7 +117,7 @@ fn should_measure_br_table_cpu_burner_with_br_table_iterations() { let module_bytes = cpu_burner_br_table(u32::MAX as i64); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::module_bytes( *DEFAULT_ACCOUNT_ADDR, module_bytes, @@ -134,7 +133,7 @@ fn should_measure_br_table_cpu_burner_with_br_table_iterations() { #[test] fn should_charge_extra_per_amount_of_br_table_elements() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); const FIXED_BLOCK_AMOUNT: usize = 256; const N_ELEMENTS: u32 = 5; diff --git a/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs b/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs index e59f7239ee..a7054db06b 100644 --- a/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs +++ b/execution_engine_testing/tests/src/test/regression/transforms_must_be_ordered.rs @@ -5,7 +5,7 @@ use rand::{rngs::StdRng, Rng, SeedableRng}; use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; use casper_types::{ execution::TransformKindV2, runtime_args, system::standard_payment, AddressableEntityHash, Key, @@ -21,7 +21,7 @@ fn contract_transforms_should_be_ordered_in_the_effects() { const N_OPS: usize = 1000; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut rng = StdRng::seed_from_u64(0); @@ -66,9 +66,9 @@ fn contract_transforms_should_be_ordered_in_the_effects() { builder .exec( ExecuteRequestBuilder::from_deploy_item( - DeployItemBuilder::new() + &DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! { + .with_standard_payment(runtime_args! { standard_payment::ARG_AMOUNT => U512::from(150_000_000_000_u64), }) .with_stored_session_hash( @@ -88,8 +88,7 @@ fn contract_transforms_should_be_ordered_in_the_effects() { .commit(); let exec_result = builder.get_exec_result_owned(1).unwrap(); - assert_eq!(exec_result.len(), 1); - let effects = exec_result[0].effects(); + let effects = exec_result.effects(); let contract = builder .get_entity_with_named_keys_by_entity_hash(contract_hash) diff --git a/execution_engine_testing/tests/src/test/stack_overflow.rs b/execution_engine_testing/tests/src/test/stack_overflow.rs index e395f5868d..c54979ca19 100644 --- a/execution_engine_testing/tests/src/test/stack_overflow.rs +++ b/execution_engine_testing/tests/src/test/stack_overflow.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::RuntimeArgs; @@ -26,7 +25,7 @@ fn runtime_stack_overflow_should_cause_unreachable_error() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder .exec(do_stack_overflow_request) .expect_failure() diff --git a/execution_engine_testing/tests/src/test/step.rs b/execution_engine_testing/tests/src/test/step.rs index 0a286ead52..82cc1730af 100644 --- a/execution_engine_testing/tests/src/test/step.rs +++ b/execution_engine_testing/tests/src/test/step.rs @@ -47,17 +47,17 @@ fn initialize_builder() -> LmdbWasmTestBuilder { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); diff --git a/execution_engine_testing/tests/src/test/storage_costs.rs b/execution_engine_testing/tests/src/test/storage_costs.rs index ebf694aa77..0006f6ae49 100644 --- a/execution_engine_testing/tests/src/test/storage_costs.rs +++ b/execution_engine_testing/tests/src/test/storage_costs.rs @@ -6,7 +6,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::DEFAULT_ACCOUNT_PUBLIC_KEY; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PROTOCOL_VERSION, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, }; #[cfg(not(feature = "use-as-wasm"))] use casper_types::DEFAULT_ADD_BID_COST; @@ -115,10 +115,10 @@ fn initialize_isolated_storage_costs() -> LmdbWasmTestBuilder { // // Isolate storage costs without host function costs, and without opcode costs // - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut upgrade_request = UpgradeRequestBuilder::new() - .with_current_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_current_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_new_protocol_version(*NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build(); @@ -146,7 +146,6 @@ fn should_verify_isolate_host_side_payment_code_is_free() { DO_NOTHING_WASM, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let account = builder @@ -184,7 +183,6 @@ fn should_verify_isolated_auction_storage_is_free() { SYSTEM_CONTRACT_HASHES_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -210,7 +208,6 @@ fn should_verify_isolated_auction_storage_is_free() { auction::ARG_DELEGATION_RATE => DELEGATION_RATE, }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let balance_before = builder.get_purse_balance(account.main_purse()); @@ -249,7 +246,6 @@ fn should_measure_gas_cost_for_storage_usage_write() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -280,7 +276,6 @@ fn should_measure_gas_cost_for_storage_usage_write() { WRITE_FUNCTION_SMALL_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder_a @@ -321,7 +316,6 @@ fn should_measure_gas_cost_for_storage_usage_write() { WRITE_FUNCTION_LARGE_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder_b @@ -356,7 +350,7 @@ fn should_measure_unisolated_gas_cost_for_storage_usage_write() { let cost_per_byte = U512::from(StorageCosts::default().gas_per_byte()); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -471,7 +465,6 @@ fn should_measure_gas_cost_for_storage_usage_add() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -502,7 +495,6 @@ fn should_measure_gas_cost_for_storage_usage_add() { ADD_FUNCTION_SMALL_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder_a @@ -543,7 +535,6 @@ fn should_measure_gas_cost_for_storage_usage_add() { ADD_FUNCTION_LARGE_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder_b @@ -580,7 +571,7 @@ fn should_measure_unisolated_gas_cost_for_storage_usage_add() { let cost_per_byte = U512::from(StorageCosts::default().gas_per_byte()); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -686,7 +677,8 @@ fn should_measure_unisolated_gas_cost_for_storage_usage_add() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_new_uref_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -695,7 +687,6 @@ fn should_verify_new_uref_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -719,7 +710,6 @@ fn should_verify_new_uref_is_charging_for_storage() { NEW_UREF_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -730,7 +720,8 @@ fn should_verify_new_uref_is_charging_for_storage() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_put_key_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -739,7 +730,6 @@ fn should_verify_put_key_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -763,7 +753,6 @@ fn should_verify_put_key_is_charging_for_storage() { PUT_KEY_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -774,7 +763,8 @@ fn should_verify_put_key_is_charging_for_storage() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_remove_key_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -783,7 +773,6 @@ fn should_verify_remove_key_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -807,7 +796,6 @@ fn should_verify_remove_key_is_charging_for_storage() { REMOVE_KEY_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -818,7 +806,8 @@ fn should_verify_remove_key_is_charging_for_storage() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_create_contract_at_hash_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -827,7 +816,6 @@ fn should_verify_create_contract_at_hash_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -851,7 +839,6 @@ fn should_verify_create_contract_at_hash_is_charging_for_storage() { CREATE_CONTRACT_PACKAGE_AT_HASH_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -862,7 +849,8 @@ fn should_verify_create_contract_at_hash_is_charging_for_storage() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_create_contract_user_group_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -871,7 +859,6 @@ fn should_verify_create_contract_user_group_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); @@ -895,7 +882,6 @@ fn should_verify_create_contract_user_group_is_charging_for_storage() { CREATE_CONTRACT_USER_GROUP_FUNCTION_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -912,7 +898,6 @@ fn should_verify_create_contract_user_group_is_charging_for_storage() { PROVISION_UREFS_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -929,7 +914,6 @@ fn should_verify_create_contract_user_group_is_charging_for_storage() { REMOVE_CONTRACT_USER_GROUP_FUNCTION, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(exec_request).expect_success().commit(); @@ -940,7 +924,8 @@ fn should_verify_create_contract_user_group_is_charging_for_storage() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_verify_subcall_new_uref_is_charging_for_storage() { let mut builder = initialize_isolated_storage_costs(); @@ -949,7 +934,6 @@ fn should_verify_subcall_new_uref_is_charging_for_storage() { STORAGE_COSTS_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(install_exec_request).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs b/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs index 1db54e6afe..7ec37cf620 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction/bids.rs @@ -10,8 +10,8 @@ use casper_engine_test_support::{ DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_CHAINSPEC_REGISTRY, DEFAULT_EXEC_CONFIG, DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, - DEFAULT_UNBONDING_DELAY, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, - SYSTEM_ADDR, TIMESTAMP_MILLIS_INCREMENT, + DEFAULT_UNBONDING_DELAY, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, + TIMESTAMP_MILLIS_INCREMENT, }; use casper_execution_engine::{ engine_state::{self, engine_config::DEFAULT_MINIMUM_DELEGATION_AMOUNT, Error}, @@ -162,7 +162,7 @@ fn should_add_new_bid() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); tmp.push(account_1); @@ -206,7 +206,7 @@ fn should_increase_existing_bid() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); tmp.push(account_1); @@ -265,7 +265,7 @@ fn should_decrease_existing_bid() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); tmp.push(account_1); @@ -333,7 +333,7 @@ fn should_run_delegate_and_undelegate() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); tmp.push(account_1); @@ -512,23 +512,23 @@ fn should_calculate_era_validators() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let account_3 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); tmp.push(account_1); @@ -677,17 +677,17 @@ fn should_get_first_seigniorage_recipients() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); @@ -704,8 +704,8 @@ fn should_get_first_seigniorage_recipients() { .with_locked_funds_period_millis(CASPER_LOCKED_FUNDS_PERIOD_MILLIS) .build(); let run_genesis_request = GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ); @@ -835,16 +835,12 @@ fn should_release_founder_stake() { builder.exec(full_unbond).commit(); - let error = { - let response = builder - .get_last_exec_result() - .expect("should have last exec result"); - let exec_response = response.last().expect("should have response"); - exec_response - .as_error() - .cloned() - .expect("should have error") - }; + let error = builder + .get_last_exec_result() + .expect("should have last exec result") + .error() + .cloned() + .expect("should have error"); assert_matches!( error, engine_state::Error::Exec(ExecError::Revert(ApiError::AuctionError(15))) @@ -855,9 +851,9 @@ fn should_release_founder_stake() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); @@ -873,8 +869,8 @@ fn should_release_founder_stake() { .build(); GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ) @@ -1002,9 +998,9 @@ fn should_fail_to_get_era_validators() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); @@ -1030,9 +1026,9 @@ fn should_fail_to_get_era_validators() { fn should_use_era_validators_endpoint_for_first_era() { let extra_accounts = vec![GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), )]; @@ -1070,28 +1066,28 @@ fn should_calculate_era_validators_multiple_new_bids() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let account_3 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), None, ); let account_4 = GenesisAccount::account( BID_ACCOUNT_2_PK.clone(), - Motes::new(BID_ACCOUNT_2_BALANCE.into()), + Motes::new(BID_ACCOUNT_2_BALANCE), None, ); tmp.push(account_1); @@ -1274,7 +1270,7 @@ fn undelegated_funds_should_be_released() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -1400,7 +1396,7 @@ fn fully_undelegated_funds_should_be_released() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -1561,7 +1557,7 @@ fn should_undelegate_delegators_when_validator_unbonds() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -1793,7 +1789,7 @@ fn should_undelegate_delegators_when_validator_fully_unbonds() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -1897,12 +1893,12 @@ fn should_undelegate_delegators_when_validator_fully_unbonds() { #[test] fn should_handle_evictions() { let activate_bid = |builder: &mut LmdbWasmTestBuilder, validator_public_key: PublicKey| { - const ARG_VALIDATOR_PUBLIC_KEY: &str = "validator_public_key"; + const ARG_VALIDATOR: &str = "validator"; let run_request = ExecuteRequestBuilder::standard( AccountHash::from(&validator_public_key), CONTRACT_ACTIVATE_BID, runtime_args! { - ARG_VALIDATOR_PUBLIC_KEY => validator_public_key, + ARG_VALIDATOR => validator_public_key, }, ) .build(); @@ -1924,33 +1920,33 @@ fn should_handle_evictions() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let account_3 = GenesisAccount::account( BID_ACCOUNT_1_PK.clone(), - Motes::new(BID_ACCOUNT_1_BALANCE.into()), + Motes::new(BID_ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(300_000.into()), + Motes::new(300_000), DelegationRate::zero(), )), ); let account_4 = GenesisAccount::account( BID_ACCOUNT_2_PK.clone(), - Motes::new(BID_ACCOUNT_2_BALANCE.into()), + Motes::new(BID_ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(400_000.into()), + Motes::new(400_000), DelegationRate::zero(), )), ); @@ -2083,31 +2079,31 @@ fn should_validate_orphaned_genesis_delegators() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); let orphaned_delegator = GenesisAccount::delegator( missing_validator, DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); tmp.push(account_1); tmp.push(account_2); @@ -2131,37 +2127,37 @@ fn should_validate_duplicated_genesis_delegators() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); let duplicated_delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); let duplicated_delegator_2 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_2.clone(), - Motes::new(DELEGATOR_2_BALANCE.into()), - Motes::new(DELEGATOR_2_STAKE.into()), + Motes::new(DELEGATOR_2_BALANCE), + Motes::new(DELEGATOR_2_STAKE), ); tmp.push(account_1); tmp.push(account_2); @@ -2186,9 +2182,9 @@ fn should_validate_delegation_rate_of_genesis_validator() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::max_value(), )), ); @@ -2211,7 +2207,7 @@ fn should_validate_bond_amount_of_genesis_validator() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new(Motes::zero(), DelegationRate::zero())), ); tmp.push(account_1); @@ -2232,22 +2228,22 @@ fn should_setup_genesis_delegators() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), - Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND.into()), 80)), + Motes::new(ACCOUNT_1_BALANCE), + Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND), 80)), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); tmp.push(account_1); tmp.push(account_2); @@ -2308,17 +2304,17 @@ fn should_not_partially_undelegate_uninitialized_vesting_schedule() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( VALIDATOR_1.clone(), DELEGATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); tmp.push(validator_1); tmp.push(delegator_1); @@ -2357,16 +2353,12 @@ fn should_not_partially_undelegate_uninitialized_vesting_schedule() { .build(); builder.exec(partial_undelegate).commit(); - let error = { - let response = builder - .get_last_exec_result() - .expect("should have last exec result"); - let exec_response = response.last().expect("should have response"); - exec_response - .as_error() - .cloned() - .expect("should have error") - }; + let error = builder + .get_last_exec_result() + .expect("should have last exec result") + .error() + .cloned() + .expect("should have error"); assert!(matches!( error, @@ -2382,17 +2374,17 @@ fn should_not_fully_undelegate_uninitialized_vesting_schedule() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( VALIDATOR_1.clone(), DELEGATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); tmp.push(validator_1); tmp.push(delegator_1); @@ -2431,16 +2423,12 @@ fn should_not_fully_undelegate_uninitialized_vesting_schedule() { .build(); builder.exec(full_undelegate).commit(); - let error = { - let response = builder - .get_last_exec_result() - .expect("should have last exec result"); - let exec_response = response.last().expect("should have response"); - exec_response - .as_error() - .cloned() - .expect("should have error") - }; + let error = builder + .get_last_exec_result() + .expect("should have last exec result") + .error() + .cloned() + .expect("should have error"); assert!(matches!( error, @@ -2456,17 +2444,17 @@ fn should_not_undelegate_vfta_holder_stake() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( VALIDATOR_1.clone(), DELEGATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - Motes::new(DELEGATOR_1_STAKE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), + Motes::new(DELEGATOR_1_STAKE), ); tmp.push(validator_1); tmp.push(delegator_1); @@ -2480,8 +2468,8 @@ fn should_not_undelegate_vfta_holder_stake() { .build(); GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, exec_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ) @@ -2562,16 +2550,12 @@ fn should_not_undelegate_vfta_holder_stake() { ) .build(); builder.exec(partial_unbond).commit(); - let error = { - let response = builder - .get_last_exec_result() - .expect("should have last exec result"); - let exec_response = response.last().expect("should have response"); - exec_response - .as_error() - .cloned() - .expect("should have error") - }; + let error = builder + .get_last_exec_result() + .expect("should have last exec result") + .error() + .cloned() + .expect("should have error"); assert!(matches!( error, @@ -2628,16 +2612,12 @@ fn should_release_vfta_holder_stake() { builder.exec(full_undelegate).commit(); - let error = { - let response = builder - .get_last_exec_result() - .expect("should have last exec result"); - let exec_response = response.last().expect("should have response"); - exec_response - .as_error() - .cloned() - .expect("should have error") - }; + let error = builder + .get_last_exec_result() + .expect("should have last exec result") + .error() + .cloned() + .expect("should have error"); assert!( matches!( @@ -2654,17 +2634,17 @@ fn should_release_vfta_holder_stake() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), + Motes::new(ACCOUNT_1_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_1_BOND.into()), + Motes::new(ACCOUNT_1_BOND), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(DELEGATOR_VFTA_STAKE.into()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::new(DELEGATOR_VFTA_STAKE), ); tmp.push(account_1); tmp.push(delegator_1); @@ -2678,8 +2658,8 @@ fn should_release_vfta_holder_stake() { .build(); GenesisRequest::new( - *DEFAULT_GENESIS_CONFIG_HASH, - *DEFAULT_PROTOCOL_VERSION, + DEFAULT_GENESIS_CONFIG_HASH, + DEFAULT_PROTOCOL_VERSION, genesis_config, DEFAULT_CHAINSPEC_REGISTRY.clone(), ) @@ -2966,7 +2946,7 @@ fn should_reset_delegators_stake_after_slashing() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).expect_success().commit(); @@ -3083,22 +3063,22 @@ fn should_validate_genesis_delegators_bond_amount() { let mut tmp: Vec = DEFAULT_ACCOUNTS.clone(); let account_1 = GenesisAccount::account( ACCOUNT_1_PK.clone(), - Motes::new(ACCOUNT_1_BALANCE.into()), - Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND.into()), 80)), + Motes::new(ACCOUNT_1_BALANCE), + Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND), 80)), ); let account_2 = GenesisAccount::account( ACCOUNT_2_PK.clone(), - Motes::new(ACCOUNT_2_BALANCE.into()), + Motes::new(ACCOUNT_2_BALANCE), Some(GenesisValidator::new( - Motes::new(ACCOUNT_2_BOND.into()), + Motes::new(ACCOUNT_2_BOND), DelegationRate::zero(), )), ); let delegator_1 = GenesisAccount::delegator( ACCOUNT_1_PK.clone(), DELEGATOR_1.clone(), - Motes::new(DELEGATOR_1_BALANCE.into()), - Motes::new(U512::zero()), + Motes::new(DELEGATOR_1_BALANCE), + Motes::zero(), ); tmp.push(account_1); tmp.push(account_2); @@ -3130,8 +3110,8 @@ fn check_validator_slots_for_accounts(accounts: usize) { let account = GenesisAccount::account( public_key, - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), - Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND.into()), 80)), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), + Some(GenesisValidator::new(Motes::new(ACCOUNT_1_BOND), 80)), ); tmp.push(account) @@ -3248,7 +3228,7 @@ fn should_delegate_and_redelegate() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -3436,7 +3416,7 @@ fn should_handle_redelegation_to_inactive_validator() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -3522,7 +3502,7 @@ fn should_handle_redelegation_to_inactive_validator() { fn should_enforce_minimum_delegation_amount() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_to_validator_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -3603,7 +3583,7 @@ fn should_enforce_minimum_delegation_amount() { fn should_allow_delegations_with_minimal_floor_amount() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_to_validator_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -3716,7 +3696,7 @@ fn should_enforce_max_delegators_per_validator_cap() { let data_dir = TempDir::new().expect("should create temp dir"); let mut builder = LmdbWasmTestBuilder::new_with_config(data_dir.path(), chainspec); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_to_validator_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -4002,7 +3982,7 @@ fn should_transfer_to_main_purse_in_case_of_redelegation_past_max_delegation_cap let data_dir = TempDir::new().expect("should create temp dir"); let mut builder = LmdbWasmTestBuilder::new_with_config(data_dir.path(), chainspec); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).expect_success().commit(); @@ -4151,7 +4131,7 @@ fn should_delegate_and_redelegate_with_eviction_regression_test() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); @@ -4197,7 +4177,7 @@ fn should_increase_existing_delegation_when_limit_exceeded() { let data_dir = TempDir::new().expect("should create temp dir"); let mut builder = LmdbWasmTestBuilder::new_with_config(data_dir.path(), chainspec); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_to_validator_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs b/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs index ed2a0ee4f8..8148e5087a 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs @@ -8,9 +8,10 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, StepRequestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_MINIMUM_DELEGATION_AMOUNT, DEFAULT_PROTOCOL_VERSION, DEFAULT_ROUND_SEIGNIORAGE_RATE, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_ROUND_SEIGNIORAGE_RATE, - PRODUCTION_RUN_GENESIS_REQUEST, SYSTEM_ADDR, TIMESTAMP_MILLIS_INCREMENT, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_ROUND_SEIGNIORAGE_RATE, + SYSTEM_ADDR, TIMESTAMP_MILLIS_INCREMENT, }; +use casper_storage::data_access_layer::AuctionMethod; use casper_types::{ self, account::AccountHash, @@ -21,7 +22,7 @@ use casper_types::{ ARG_DELEGATOR, ARG_PUBLIC_KEY, ARG_REWARDS_MAP, ARG_VALIDATOR, DELEGATION_RATE_DENOMINATOR, METHOD_DISTRIBUTE, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, }, - EntityAddr, EraId, Key, ProtocolVersion, PublicKey, SecretKey, U512, + EntityAddr, EraId, HoldsEpoch, Key, ProtocolVersion, PublicKey, SecretKey, Timestamp, U512, }; const ARG_ENTRY_POINT: &str = "entry_point"; @@ -251,11 +252,12 @@ fn should_distribute_delegation_rate_zero() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); + let initial_supply = builder.total_supply(None, protocol_version); + let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); assert_eq!(total_payout, expected_total_reward_integer); @@ -516,13 +518,18 @@ fn should_withdraw_bids_after_distribute() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + let protocol_version = DEFAULT_PROTOCOL_VERSION; + let total_payout = builder.base_round_reward(None, protocol_version); // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); - let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; + let initial_supply = builder.total_supply(None, protocol_version); + let rate = builder.round_seigniorage_rate(None, protocol_version); + + let expected_total_reward = rate * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); + assert_eq!(total_payout, expected_total_reward_integer); for request in post_genesis_requests { @@ -532,7 +539,7 @@ fn should_withdraw_bids_after_distribute() { for _ in 0..=builder.get_auction_delay() { let step_request = StepRequestBuilder::new() .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(ProtocolVersion::V1_0_0) + .with_protocol_version(protocol_version) .with_next_era_id(builder.get_era().successor()) .with_run_auction(true) .build(); @@ -640,6 +647,7 @@ fn should_withdraw_bids_after_distribute() { "delegator 1 should have a stake" ); let undelegate_amount = U512::from(DELEGATOR_1_STAKE) + delegator_1_actual_payout; + undelegate( &mut builder, *DELEGATOR_1_ADDR, @@ -723,13 +731,13 @@ fn should_withdraw_bids_after_distribute() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_distribute_rewards_after_restaking_delegated_funds() { - const VALIDATOR_1_STAKE: u64 = 1_000_000_000_000; - const DELEGATOR_1_STAKE: u64 = 1_000_000_000_000; - const DELEGATOR_2_STAKE: u64 = 1_000_000_000_000; + const VALIDATOR_1_STAKE: u64 = 7_000_000_000_000_000; + const DELEGATOR_1_STAKE: u64 = 5_000_000_000_000_000; + const DELEGATOR_2_STAKE: u64 = 5_000_000_000_000_000; const TOTAL_DELEGATOR_STAKE: u64 = DELEGATOR_1_STAKE + DELEGATOR_2_STAKE; - const TOTAL_STAKE: u64 = TOTAL_DELEGATOR_STAKE + VALIDATOR_1_STAKE; const VALIDATOR_1_DELEGATION_RATE: DelegationRate = 0; @@ -818,322 +826,231 @@ fn should_distribute_rewards_after_restaking_delegated_funds() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); - let expected_total_reward_1 = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; - let expected_total_reward_1_integer = expected_total_reward_1.to_integer(); - assert_eq!(total_payout, expected_total_reward_1_integer); + let initial_supply = builder.total_supply(None, protocol_version); + let initial_rate = builder.round_seigniorage_rate(None, protocol_version); + let initial_round_reward = builder.base_round_reward(None, protocol_version); + + let initial_expected_reward_rate = initial_rate * initial_supply; + assert_eq!( + initial_round_reward, + initial_expected_reward_rate.to_integer() + ); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); } - for _ in 0..=builder.get_auction_delay() { - let step_request = StepRequestBuilder::new() - .with_parent_state_hash(builder.get_post_state_hash()) - .with_protocol_version(ProtocolVersion::V1_0_0) - .with_next_era_id(builder.get_era().successor()) - .with_run_auction(true) - .build(); + // we need to crank forward because our validator is not a genesis validator + builder.advance_eras_by_default_auction_delay(); - assert!( - builder.step(step_request).is_success(), - "must execute step successfully" + let mut era = builder.get_era(); + let mut round_reward = initial_round_reward; + let mut total_supply = initial_supply; + let mut expected_reward_rate = initial_expected_reward_rate; + let mut validator_stake = U512::from(VALIDATOR_1_STAKE); + let mut delegator_1_stake = U512::from(DELEGATOR_1_STAKE); + let mut delegator_2_stake = U512::from(DELEGATOR_2_STAKE); + let mut total_delegator_stake = U512::from(TOTAL_DELEGATOR_STAKE); + let mut total_stake = U512::from(VALIDATOR_1_STAKE + TOTAL_DELEGATOR_STAKE); + for idx in 0..10 { + let rewards = { + let mut rewards = BTreeMap::new(); + rewards.insert(VALIDATOR_1.clone(), round_reward); + rewards + }; + + let result = builder.distribute(None, protocol_version, rewards, Timestamp::now().millis()); + assert!(result.is_success(), "failed to distribute {:?}", result); + builder.advance_era(); + let current_era = builder.get_era(); + assert_eq!( + era.successor(), + current_era, + "unexpected era {:?}", + current_era ); - } + era = current_era; - let mut rewards = BTreeMap::new(); - rewards.insert(VALIDATOR_1.clone(), total_payout); + let updated_round_reward = builder.base_round_reward(None, protocol_version); + round_reward = updated_round_reward; - let distribute_request = ExecuteRequestBuilder::contract_call_by_hash( - *SYSTEM_ADDR, - builder.get_auction_contract_hash(), - METHOD_DISTRIBUTE, - runtime_args! { - ARG_ENTRY_POINT => METHOD_DISTRIBUTE, - ARG_REWARDS_MAP => rewards - }, - ) - .build(); - - builder.exec(distribute_request).commit().expect_success(); - - let validator_1_staked_amount_1 = get_validator_bid(&mut builder, VALIDATOR_1.clone()) - .expect("should have validator bid") - .staked_amount(); - let delegator_1_staked_amount_1 = - get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_1.clone()); - let delegator_2_staked_amount_1 = - get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_2.clone()); - - let delegators_share = { - let commission_rate = Ratio::new( - U512::from(VALIDATOR_1_DELEGATION_RATE), - U512::from(DELEGATION_RATE_DENOMINATOR), + let updated_validator_stake = get_validator_bid(&mut builder, VALIDATOR_1.clone()) + .expect("should have validator bid") + .staked_amount(); + assert!( + updated_validator_stake > validator_stake, + "validator stake should go up" ); - let reward_multiplier = - Ratio::new(U512::from(TOTAL_DELEGATOR_STAKE), U512::from(TOTAL_STAKE)); - let delegator_reward = expected_total_reward_1 - .checked_mul(&reward_multiplier) - .expect("should get delegator reward ratio"); - let commission = delegator_reward - .checked_mul(&commission_rate) - .expect("must get delegator reward"); - delegator_reward.checked_sub(&commission).unwrap() - }; - - let delegator_1_expected_payout_1 = { - let reward_multiplier = Ratio::new( - U512::from(DELEGATOR_1_STAKE), - U512::from(TOTAL_DELEGATOR_STAKE), + let updated_delegator_1_stake = + get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_1.clone()); + assert!( + updated_delegator_1_stake > delegator_1_stake, + "delegator 1 stake should go up" ); - delegators_share - .checked_mul(&reward_multiplier) - .map(|ratio| ratio.to_integer()) - .expect("must get delegator 1 reward") - }; - - let delegator_2_expected_payout_1 = { - let reward_multiplier = Ratio::new( - U512::from(DELEGATOR_2_STAKE), - U512::from(TOTAL_DELEGATOR_STAKE), + let updated_delegator_2_stake = + get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_2.clone()); + assert!( + updated_delegator_2_stake > delegator_2_stake, + "delegator 2 stake should go up was: {:?} is: {:?}", + delegator_2_stake, + updated_delegator_2_stake, ); - delegators_share - .checked_mul(&reward_multiplier) - .map(|ratio| ratio.to_integer()) - .expect("must get delegator 2 reward") - }; - - let validator_1_actual_payout_1 = { - let validator_stake_before = U512::from(VALIDATOR_1_STAKE); - let validator_stake_after = validator_1_staked_amount_1; - - validator_stake_after - validator_stake_before - }; - - let validator_1_expected_payout_1 = { - let total_delegator_payout = delegator_1_expected_payout_1 + delegator_2_expected_payout_1; - let validator_share = expected_total_reward_1 - Ratio::from(total_delegator_payout); - validator_share.to_integer() - }; - assert_eq!(validator_1_actual_payout_1, validator_1_expected_payout_1); - - let delegator_1_actual_payout_1 = { - let delegator_stake_before = U512::from(DELEGATOR_1_STAKE); - let delegator_stake_after = delegator_1_staked_amount_1; - - delegator_stake_after - delegator_stake_before - }; - - assert_eq!(delegator_1_actual_payout_1, delegator_1_expected_payout_1); - - let delegator_2_actual_payout_1 = { - let delegator_stake_before = U512::from(DELEGATOR_2_STAKE); - let delegator_stake_after = delegator_2_staked_amount_1; - delegator_stake_after - delegator_stake_before - }; - - assert_eq!(delegator_2_actual_payout_1, delegator_2_expected_payout_1); - - let era_info_1 = get_era_info(&mut builder); - - assert!(matches!( - era_info_1.select(VALIDATOR_1.clone()).next(), - Some(SeigniorageAllocation::Validator { validator_public_key, amount }) - if *validator_public_key == *VALIDATOR_1 && *amount == validator_1_expected_payout_1 - )); - - assert!(matches!( - era_info_1.select(DELEGATOR_1.clone()).next(), - Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) - if *delegator_public_key == *DELEGATOR_1 && *amount == delegator_1_expected_payout_1 - )); - - assert!(matches!( - era_info_1.select(DELEGATOR_2.clone()).next(), - Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) - if *delegator_public_key == *DELEGATOR_2 && *amount == delegator_2_expected_payout_1 - )); - - // Next round of rewards - let total_supply_2 = builder.total_supply(None); - let total_payout_2 = builder.base_round_reward(None); - assert!(total_supply_2 > initial_supply); - - let expected_total_reward_2 = *GENESIS_ROUND_SEIGNIORAGE_RATE * total_supply_2; - - let expected_total_reward_2_integer = expected_total_reward_2.to_integer(); - assert_eq!(total_payout_2, expected_total_reward_2_integer); - - let mut rewards = BTreeMap::new(); - rewards.insert(VALIDATOR_1.clone(), total_payout_2); - - let distribute_request = ExecuteRequestBuilder::contract_call_by_hash( - *SYSTEM_ADDR, - builder.get_auction_contract_hash(), - METHOD_DISTRIBUTE, - runtime_args! { - ARG_ENTRY_POINT => METHOD_DISTRIBUTE, - ARG_REWARDS_MAP => rewards - }, - ) - .build(); - - builder.exec(distribute_request).commit().expect_success(); - - let validator_1_staked_amount_2 = get_validator_bid(&mut builder, VALIDATOR_1.clone()) - .expect("should have validator bid") - .staked_amount(); - let delegator_1_staked_amount_2 = - get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_1.clone()); - let delegator_2_staked_amount_2 = - get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_2.clone()); - - let delegators_share_2 = { - let commission_rate = Ratio::new( - U512::from(VALIDATOR_1_DELEGATION_RATE), - U512::from(DELEGATION_RATE_DENOMINATOR), + let updated_total_delegator_stake = updated_delegator_1_stake + updated_delegator_2_stake; + assert!( + updated_total_delegator_stake > total_delegator_stake, + "total delegator stake should go up" ); - let reward_multiplier = - Ratio::new(U512::from(TOTAL_DELEGATOR_STAKE), U512::from(TOTAL_STAKE)); - let delegator_reward = expected_total_reward_2 - .checked_mul(&reward_multiplier) - .expect("should get delegator reward ratio"); - let commission = delegator_reward - .checked_mul(&commission_rate) - .expect("must get delegator reward"); - delegator_reward.checked_sub(&commission).unwrap() - }; - - let delegator_1_expected_payout_2 = { - let reward_multiplier = Ratio::new( - U512::from(DELEGATOR_1_STAKE), - U512::from(TOTAL_DELEGATOR_STAKE), + total_delegator_stake = updated_total_delegator_stake; + let updated_total_stake = updated_validator_stake + updated_total_delegator_stake; + assert!( + updated_total_stake > total_stake, + "total stake should go up" ); - delegators_share_2 - .checked_mul(&reward_multiplier) - .map(|ratio| ratio.to_integer()) - .expect("must get delegator 1 reward") - }; - let delegator_2_expected_payout_2 = { - let reward_multiplier = Ratio::new( - U512::from(DELEGATOR_2_STAKE), - U512::from(TOTAL_DELEGATOR_STAKE), + let delegators_share = { + let commission_rate = Ratio::new( + U512::from(VALIDATOR_1_DELEGATION_RATE), + U512::from(DELEGATION_RATE_DENOMINATOR), + ); + let reward_multiplier = Ratio::new(updated_total_delegator_stake, updated_total_stake); + let delegator_reward = expected_reward_rate + .checked_mul(&reward_multiplier) + .expect("should get delegator reward ratio"); + let commission = delegator_reward + .checked_mul(&commission_rate) + .expect("must get delegator reward"); + delegator_reward.checked_sub(&commission).unwrap() + }; + + let delegator_1_expected_payout = { + let reward_multiplier = + Ratio::new(updated_delegator_1_stake, updated_total_delegator_stake); + delegators_share + .checked_mul(&reward_multiplier) + .map(|ratio| ratio.to_integer()) + .expect("must get delegator 1 reward") + }; + + let delegator_2_expected_payout = { + let reward_multiplier = + Ratio::new(updated_delegator_2_stake, updated_total_delegator_stake); + delegators_share + .checked_mul(&reward_multiplier) + .map(|ratio| ratio.to_integer()) + .expect("must get delegator 2 reward") + }; + + let validator_1_actual_payout = updated_validator_stake - validator_stake; + + let validator_1_expected_payout = (expected_reward_rate + - Ratio::from(delegator_1_expected_payout + delegator_2_expected_payout)) + .to_integer(); + assert_eq!(validator_1_actual_payout, validator_1_expected_payout); + + let delegator_1_actual_payout = updated_delegator_1_stake - delegator_1_stake; + assert_eq!(delegator_1_actual_payout, delegator_1_expected_payout); + + let delegator_2_actual_payout = updated_delegator_2_stake - delegator_2_stake; + assert_eq!(delegator_2_actual_payout, delegator_2_expected_payout); + + let updated_era_info = get_era_info(&mut builder); + + assert!(matches!( + updated_era_info.select(VALIDATOR_1.clone()).next(), + Some(SeigniorageAllocation::Validator { validator_public_key, amount }) + if *validator_public_key == *VALIDATOR_1 && *amount == validator_1_expected_payout + )); + + assert!(matches!( + updated_era_info.select(DELEGATOR_1.clone()).next(), + Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) + if *delegator_public_key == *DELEGATOR_1 && *amount == delegator_1_expected_payout + )); + + assert!(matches!( + updated_era_info.select(DELEGATOR_2.clone()).next(), + Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) + if *delegator_public_key == *DELEGATOR_2 && *amount == delegator_2_expected_payout + )); + + // Next round of rewards + let updated_supply = builder.total_supply(None, protocol_version); + assert!(updated_supply > total_supply); + total_supply = updated_supply; + + let updated_rate = builder.round_seigniorage_rate(None, protocol_version); + expected_reward_rate = updated_rate * total_supply; + + // lets churn the bids just to have some fun + let undelegate_amount = delegator_1_expected_payout - 1; + let undelegate_result = builder.bidding( + None, + protocol_version, + (*DELEGATOR_1_ADDR).into(), + AuctionMethod::Undelegate { + validator: VALIDATOR_1.clone(), + delegator: DELEGATOR_1.clone(), + amount: undelegate_amount, + }, ); - delegators_share_2 - .checked_mul(&reward_multiplier) - .map(|ratio| ratio.to_integer()) - .expect("must get delegator 2 reward") - }; - - let validator_1_expected_payout_2 = { - let total_delegator_payout = delegator_1_expected_payout_2 + delegator_2_expected_payout_2; - let validator_share = expected_total_reward_2 - Ratio::from(total_delegator_payout); - validator_share.to_integer() - }; - - let validator_1_actual_payout_2 = { - let validator_stake_before = validator_1_staked_amount_1; - let validator_stake_after = validator_1_staked_amount_2; - validator_stake_after - validator_stake_before - }; - assert_eq!(validator_1_actual_payout_2, validator_1_expected_payout_2); - - let delegator_1_actual_payout_2 = { - let delegator_stake_before = delegator_1_staked_amount_1; - let delegator_stake_after = delegator_1_staked_amount_2; - - delegator_stake_after - delegator_stake_before - }; - - assert_eq!(delegator_1_actual_payout_2, delegator_1_expected_payout_2); - - let delegator_2_actual_payout_2 = { - let delegator_stake_before = delegator_2_staked_amount_1; - let delegator_stake_after = delegator_2_staked_amount_2; - delegator_stake_after - delegator_stake_before - }; - - assert_eq!(delegator_2_actual_payout_2, delegator_2_expected_payout_2); - - // Ensure that paying out next set of rewards gives higher payouts than previous time. - assert!(validator_1_actual_payout_2 > validator_1_actual_payout_1); - assert!(delegator_1_actual_payout_2 > delegator_1_actual_payout_1); - assert!(delegator_2_actual_payout_2 > delegator_2_actual_payout_1); - - let era_info_2 = get_era_info(&mut builder); - - assert_ne!(era_info_2, era_info_1); - - assert!(matches!( - era_info_2.select(VALIDATOR_1.clone()).next(), - Some(SeigniorageAllocation::Validator { validator_public_key, amount, .. }) - if *validator_public_key == *VALIDATOR_1 && *amount == validator_1_expected_payout_2 - )); - - assert!(matches!( - era_info_2.select(DELEGATOR_1.clone()).next(), - Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) - if *delegator_public_key == *DELEGATOR_1 && *amount == delegator_1_expected_payout_2 - )); - - assert!(matches!( - era_info_2.select(DELEGATOR_2.clone()).next(), - Some(SeigniorageAllocation::Delegator { delegator_public_key, amount, .. }) - if *delegator_public_key == *DELEGATOR_2 && *amount == delegator_2_expected_payout_2 - )); + assert!(undelegate_result.is_success(), "{:?}", undelegate_result); + builder.commit_transforms(builder.get_post_state_hash(), undelegate_result.effects()); + delegator_1_stake = + get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_1.clone()); - // Withdraw delegator rewards - let delegator_1_rewards = delegator_1_actual_payout_1 + delegator_1_actual_payout_2; - undelegate( - &mut builder, - *DELEGATOR_1_ADDR, - DELEGATOR_1.clone(), - VALIDATOR_1.clone(), - delegator_1_rewards, - ); - let remaining_delegator_1_bid = - get_delegator_bid(&mut builder, VALIDATOR_1.clone(), DELEGATOR_1.clone()) - .expect("should have delegator bid"); - assert_eq!( - remaining_delegator_1_bid.staked_amount(), - U512::from(DELEGATOR_1_STAKE) - ); + let updelegate_amount = U512::from(1_000_000); + let updelegate_result = builder.bidding( + None, + protocol_version, + (*DELEGATOR_2_ADDR).into(), + AuctionMethod::Delegate { + max_delegators_per_validator: u32::MAX, + minimum_delegation_amount: updelegate_amount.as_u64(), + validator: VALIDATOR_1.clone(), + delegator: DELEGATOR_2.clone(), + amount: updelegate_amount, + holds_epoch: HoldsEpoch::NOT_APPLICABLE, + }, + ); + assert!(updelegate_result.is_success(), "{:?}", updelegate_result); + builder.commit_transforms(builder.get_post_state_hash(), undelegate_result.effects()); + delegator_2_stake = + get_delegator_staked_amount(&mut builder, VALIDATOR_1.clone(), DELEGATOR_2.clone()); - let delegator_2_rewards = delegator_2_actual_payout_1 + delegator_2_actual_payout_2; - undelegate( - &mut builder, - *DELEGATOR_2_ADDR, - DELEGATOR_2.clone(), - VALIDATOR_1.clone(), - delegator_2_rewards, - ); - let remaining_delegator_2_bid = - get_delegator_bid(&mut builder, VALIDATOR_1.clone(), DELEGATOR_2.clone()) - .expect("should have delegator bid"); - assert_eq!( - remaining_delegator_2_bid.staked_amount(), - U512::from(DELEGATOR_2_STAKE) - ); + let auction_method = { + let amount = U512::from(10_000_000); + if idx % 2 == 0 { + AuctionMethod::AddBid { + public_key: VALIDATOR_1.clone(), + amount, + delegation_rate: 0, + holds_epoch: HoldsEpoch::NOT_APPLICABLE, + } + } else { + AuctionMethod::WithdrawBid { + public_key: VALIDATOR_1.clone(), + amount, + } + } + }; + let bid_flip_result = builder.bidding( + None, + protocol_version, + (*VALIDATOR_1_ADDR).into(), + auction_method, + ); + assert!(bid_flip_result.is_success(), "{:?}", bid_flip_result); + builder.commit_transforms(builder.get_post_state_hash(), undelegate_result.effects()); + validator_stake = get_validator_bid(&mut builder, VALIDATOR_1.clone()) + .expect("should have validator bid") + .staked_amount(); - // Withdraw validator rewards - let validator_1_rewards = validator_1_actual_payout_1 + validator_1_actual_payout_2; - withdraw_bid( - &mut builder, - *VALIDATOR_1_ADDR, - VALIDATOR_1.clone(), - validator_1_rewards, - ); - let remaining_validator_1_bid = - get_validator_bid(&mut builder, VALIDATOR_1.clone()).expect("should have validator bid"); - assert_eq!( - remaining_validator_1_bid.staked_amount(), - U512::from(VALIDATOR_1_STAKE) - ); + total_stake = validator_stake + delegator_1_stake + delegator_2_stake; + } } #[ignore] @@ -1232,11 +1149,12 @@ fn should_distribute_delegation_rate_half() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); + let initial_supply = builder.total_supply(None, protocol_version); + let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); assert_eq!(total_payout, expected_total_reward_integer); @@ -1463,10 +1381,11 @@ fn should_distribute_delegation_rate_full() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -1644,11 +1563,12 @@ fn should_distribute_uneven_delegation_rate_zero() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); + let initial_supply = builder.total_supply(None, protocol_version); + let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); assert_eq!(total_payout, expected_total_reward_integer); @@ -1946,11 +1866,12 @@ fn should_distribute_with_multiple_validators_and_delegators() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); + let initial_supply = builder.total_supply(None, protocol_version); + let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); assert_eq!(total_payout, expected_total_reward_integer); @@ -2277,11 +2198,12 @@ fn should_distribute_with_multiple_validators_and_shared_delegator() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); - let total_payout = builder.base_round_reward(None); + let initial_supply = builder.total_supply(None, protocol_version); + let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); assert_eq!(total_payout, expected_total_reward_integer); @@ -2633,16 +2555,17 @@ fn should_increase_total_supply_after_distribute() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); } - let post_genesis_supply = builder.total_supply(None); + let post_genesis_supply = builder.total_supply(None, protocol_version); assert_eq!( initial_supply, post_genesis_supply, @@ -2655,7 +2578,7 @@ fn should_increase_total_supply_after_distribute() { timestamp_millis += TIMESTAMP_MILLIS_INCREMENT; } - let post_auction_supply = builder.total_supply(None); + let post_auction_supply = builder.total_supply(None, protocol_version); assert_eq!( initial_supply, post_auction_supply, "total supply should remain unchanged regardless of auction" @@ -2668,26 +2591,28 @@ fn should_increase_total_supply_after_distribute() { rewards.insert(VALIDATOR_2.clone(), total_payout); rewards.insert(VALIDATOR_3.clone(), total_payout); - let distribute_request = ExecuteRequestBuilder::contract_call_by_hash( - *SYSTEM_ADDR, - builder.get_auction_contract_hash(), - METHOD_DISTRIBUTE, - runtime_args! { - ARG_ENTRY_POINT => METHOD_DISTRIBUTE, - ARG_REWARDS_MAP => rewards - }, - ) - .build(); - - builder.exec(distribute_request).commit().expect_success(); - - let post_distribute_supply = builder.total_supply(None); - assert!( - initial_supply < post_distribute_supply, - "total supply should increase after distribute ({} >= {})", - initial_supply, - post_distribute_supply - ); + for _ in 0..5 { + let distribute_request = ExecuteRequestBuilder::contract_call_by_hash( + *SYSTEM_ADDR, + builder.get_auction_contract_hash(), + METHOD_DISTRIBUTE, + runtime_args! { + ARG_ENTRY_POINT => METHOD_DISTRIBUTE, + ARG_REWARDS_MAP => rewards.clone() + }, + ) + .build(); + + builder.exec(distribute_request).expect_success().commit(); + + let post_distribute_supply = builder.total_supply(None, protocol_version); + assert!( + initial_supply < post_distribute_supply, + "total supply should increase after distribute ({} >= {})", + initial_supply, + post_distribute_supply + ); + } } #[ignore] @@ -2810,16 +2735,17 @@ fn should_not_create_purses_during_distribute() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); } - let post_genesis_supply = builder.total_supply(None); + let post_genesis_supply = builder.total_supply(None, protocol_version); assert_eq!( initial_supply, post_genesis_supply, @@ -2832,7 +2758,7 @@ fn should_not_create_purses_during_distribute() { timestamp_millis += TIMESTAMP_MILLIS_INCREMENT; } - let post_auction_supply = builder.total_supply(None); + let post_auction_supply = builder.total_supply(None, protocol_version); assert_eq!( initial_supply, post_auction_supply, "total supply should remain unchanged regardless of auction" @@ -2865,7 +2791,7 @@ fn should_not_create_purses_during_distribute() { number_of_purses_before_distribute ); - let post_distribute_supply = builder.total_supply(None); + let post_distribute_supply = builder.total_supply(None, protocol_version); assert!( initial_supply < post_distribute_supply, "total supply should increase after distribute ({} >= {})", @@ -2971,10 +2897,11 @@ fn should_distribute_delegation_rate_full_after_upgrading() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); let expected_total_reward_before = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward_before.to_integer(); @@ -3040,10 +2967,10 @@ fn should_distribute_delegation_rate_full_after_upgrading() { // // Update round seigniorage rate into 50% of default value // - let new_seigniorage_multiplier = Ratio::new_raw(1, 10); + let new_seigniorage_multiplier = Ratio::new_raw(1, 2); let new_round_seigniorage_rate = DEFAULT_ROUND_SEIGNIORAGE_RATE * new_seigniorage_multiplier; - let old_protocol_version = *DEFAULT_PROTOCOL_VERSION; + let old_protocol_version = DEFAULT_PROTOCOL_VERSION; let sem_ver = old_protocol_version.value(); let new_protocol_version = ProtocolVersion::from_parts(sem_ver.major, sem_ver.minor, sem_ver.patch + 1); @@ -3060,7 +2987,7 @@ fn should_distribute_delegation_rate_full_after_upgrading() { builder.upgrade(&mut upgrade_request); - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(None, protocol_version); for _ in 0..5 { builder.advance_era(); @@ -3089,22 +3016,6 @@ fn should_distribute_delegation_rate_full_after_upgrading() { let mut rewards = BTreeMap::new(); rewards.insert(VALIDATOR_1.clone(), expected_total_reward_integer); - /* - let distribute_request = ExecuteRequestBuilder::contract_call_by_hash( - *SYSTEM_ADDR, - builder.get_auction_contract_hash(), - METHOD_DISTRIBUTE, - runtime_args! { - ARG_ENTRY_POINT => METHOD_DISTRIBUTE, - ARG_REWARDS_MAP => rewards - }, - ) - .with_protocol_version(new_protocol_version) - .build(); - - builder.exec(distribute_request).commit().expect_success(); - */ - let validator_1_balance_after = { let validator_staked_amount = get_validator_bid(&mut builder, VALIDATOR_1.clone()) .expect("should have validator bid") @@ -3146,9 +3057,9 @@ fn should_distribute_delegation_rate_full_after_upgrading() { validator_1_balance_after + delegator_1_balance_after + delegator_2_balance_after; assert_eq!(total_payout_after, expected_total_reward_after); - assert!(expected_validator_1_payout_before > expected_validator_1_balance_after); // expected amount after decreasing seigniorage rate is lower than the first amount - assert!(total_payout_before > total_payout_after); // expected total payout after decreasing - // rate is lower than the first payout + // expected amount after reducing the seigniorage rate is lower than the first amount + assert!(expected_validator_1_payout_before > expected_validator_1_balance_after); + assert!(total_payout_before > total_payout_after); } // In this test, we set up a validator and a delegator, then the delegator delegates to the @@ -3164,7 +3075,7 @@ fn should_not_restake_after_full_unbond() { const VALIDATOR_1_DELEGATION_RATE: DelegationRate = 0; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // advance past the initial auction delay due to special condition of post-genesis behavior. @@ -3295,7 +3206,7 @@ fn delegator_full_unbond_during_first_reward_era() { const VALIDATOR_1_DELEGATION_RATE: DelegationRate = 0; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // advance past the initial auction delay due to special condition of post-genesis behavior. builder.advance_eras_by_default_auction_delay(); diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs b/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs index f99b7bbbaf..e478a7736a 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction_bidding.rs @@ -1,11 +1,12 @@ use num_traits::Zero; use casper_engine_test_support::{ - utils, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNTS, - DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_GENESIS_TIMESTAMP_MILLIS, - DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PAYMENT, DEFAULT_PROPOSER_PUBLIC_KEY, - DEFAULT_PROTOCOL_VERSION, DEFAULT_UNBONDING_DELAY, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, SYSTEM_ADDR, TIMESTAMP_MILLIS_INCREMENT, + utils, ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, + UpgradeRequestBuilder, DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, + DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PAYMENT, + DEFAULT_PROPOSER_PUBLIC_KEY, DEFAULT_PROTOCOL_VERSION, DEFAULT_UNBONDING_DELAY, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, + TIMESTAMP_MILLIS_INCREMENT, }; use casper_execution_engine::{engine_state::Error as EngineError, execution::ExecError}; @@ -48,7 +49,7 @@ const DELEGATION_RATE: DelegationRate = 42; fn should_run_successful_bond_and_unbond_and_slashing() { let default_public_key_arg = DEFAULT_ACCOUNT_PUBLIC_KEY.clone(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -198,17 +199,13 @@ fn should_fail_bonding_with_insufficient_funds_directly() { let transfer_amount = U512::from(MINIMUM_ACCOUNT_CREATION_BALANCE); let delegation_rate: DelegationRate = 10; - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let transfer_args = runtime_args! { - mint::ARG_TARGET => new_validator_hash, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => Some(1u64), - }; - let exec_request = - ExecuteRequestBuilder::transfer(*DEFAULT_ACCOUNT_ADDR, transfer_args).build(); + let exec_request = TransferRequestBuilder::new(transfer_amount, new_validator_hash) + .with_transfer_id(1) + .build(); - builder.exec(exec_request).expect_success().commit(); + builder.transfer_and_commit(exec_request).expect_success(); let new_validator_account = builder .get_entity_by_account_hash(new_validator_hash) @@ -244,7 +241,8 @@ fn should_fail_bonding_with_insufficient_funds_directly() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_fail_bonding_with_insufficient_funds() { let account_1_secret_key = SecretKey::ed25519_from_bytes([123; SecretKey::ED25519_LENGTH]).unwrap(); @@ -275,24 +273,24 @@ fn should_fail_bonding_with_insufficient_funds() { let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .commit(); builder.exec(exec_request_2).commit(); - let response = builder + let exec_result = builder .get_exec_result_owned(1) - .expect("should have a response"); - - assert_eq!(response.len(), 1); - let exec_result = response[0].as_error().expect("should have error"); + .expect("should have a response") + .error() + .cloned() + .expect("should have error"); assert!( matches!( exec_result, EngineError::Exec(ExecError::Revert(ApiError::Mint(mint_error)) ) - if *mint_error == mint::Error::InsufficientFunds as u8), + if mint_error == mint::Error::InsufficientFunds as u8), "{:?}", exec_result ); @@ -313,7 +311,7 @@ fn should_fail_unbonding_validator_with_locked_funds() { account_1_public_key.clone(), Motes::new(account_1_balance), Some(GenesisValidator::new( - Motes::new(GENESIS_VALIDATOR_STAKE.into()), + Motes::new(GENESIS_VALIDATOR_STAKE), DelegationRate::zero(), )), ); @@ -339,11 +337,7 @@ fn should_fail_unbonding_validator_with_locked_funds() { builder.exec(exec_request_2).commit(); - let response = builder - .get_exec_result_owned(0) - .expect("should have a response"); - - let error_message = utils::get_error_message(response); + let error_message = builder.get_error_message().expect("should have a result"); // handle_payment::Error::NotBonded => 0 assert!( @@ -371,15 +365,11 @@ fn should_fail_unbonding_validator_without_bonding_first() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request).commit(); - let response = builder - .get_exec_result_owned(0) - .expect("should have a response"); - - let error_message = utils::get_error_message(response); + let error_message = builder.get_error_message().expect("should have a result"); assert!( error_message.contains(&format!( @@ -400,7 +390,7 @@ fn should_run_successful_bond_and_unbond_with_release() { DEFAULT_GENESIS_TIMESTAMP_MILLIS + DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -556,11 +546,11 @@ fn should_run_successful_unbond_funds_after_changing_unbonding_delay() { DEFAULT_GENESIS_TIMESTAMP_MILLIS + DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS; let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let new_unbonding_delay = DEFAULT_UNBONDING_DELAY + 5; - let old_protocol_version = *DEFAULT_PROTOCOL_VERSION; + let old_protocol_version = DEFAULT_PROTOCOL_VERSION; let sem_ver = old_protocol_version.value(); let new_protocol_version = ProtocolVersion::from_parts(sem_ver.major, sem_ver.minor, sem_ver.patch + 1); @@ -591,7 +581,6 @@ fn should_run_successful_unbond_funds_after_changing_unbonding_delay() { "amount" => U512::from(TRANSFER_AMOUNT) }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(exec_request).expect_success().commit(); @@ -609,7 +598,6 @@ fn should_run_successful_unbond_funds_after_changing_unbonding_delay() { ARG_DELEGATION_RATE => DELEGATION_RATE, }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(exec_request_1).expect_success().commit(); @@ -646,7 +634,6 @@ fn should_run_successful_unbond_funds_after_changing_unbonding_delay() { ARG_PUBLIC_KEY => default_public_key_arg.clone(), }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(exec_request_2).expect_success().commit(); diff --git a/execution_engine_testing/tests/src/test/system_contracts/genesis.rs b/execution_engine_testing/tests/src/test/system_contracts/genesis.rs index 3776e4c698..f0b5bebb7f 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/genesis.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/genesis.rs @@ -3,7 +3,7 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ ChainspecConfig, LmdbWasmTestBuilder, DEFAULT_AUCTION_DELAY, DEFAULT_CHAINSPEC_REGISTRY, - DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, + DEFAULT_GENESIS_TIMESTAMP_MILLIS, DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, DEFAULT_ROUND_SEIGNIORAGE_RATE, DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY, DEFAULT_VALIDATOR_SLOTS, DEFAULT_WASM_CONFIG, }; @@ -11,7 +11,7 @@ use casper_storage::data_access_layer::GenesisRequest; use casper_types::{ account::AccountHash, addressable_entity::EntityKindTag, system::auction::DelegationRate, GenesisAccount, GenesisConfigBuilder, GenesisValidator, Key, Motes, ProtocolVersion, PublicKey, - SecretKey, StoredValue, DEFAULT_FEE_HANDLING, DEFAULT_REFUND_HANDLING, U512, + SecretKey, StoredValue, U512, }; const GENESIS_CONFIG_HASH: [u8; 32] = [127; 32]; @@ -33,8 +33,8 @@ static ACCOUNT_2_ADDR: Lazy = Lazy::new(|| AccountHash::from(&*ACCO static GENESIS_CUSTOM_ACCOUNTS: Lazy> = Lazy::new(|| { let account_1 = { - let account_1_balance = Motes::new(ACCOUNT_1_BALANCE.into()); - let account_1_bonded_amount = Motes::new(ACCOUNT_1_BONDED_AMOUNT.into()); + let account_1_balance = Motes::new(ACCOUNT_1_BALANCE); + let account_1_bonded_amount = Motes::new(ACCOUNT_1_BONDED_AMOUNT); GenesisAccount::account( ACCOUNT_1_PUBLIC_KEY.clone(), account_1_balance, @@ -45,8 +45,8 @@ static GENESIS_CUSTOM_ACCOUNTS: Lazy> = Lazy::new(|| { ) }; let account_2 = { - let account_2_balance = Motes::new(ACCOUNT_2_BALANCE.into()); - let account_2_bonded_amount = Motes::new(ACCOUNT_2_BONDED_AMOUNT.into()); + let account_2_balance = Motes::new(ACCOUNT_2_BALANCE); + let account_2_bonded_amount = Motes::new(ACCOUNT_2_BONDED_AMOUNT); GenesisAccount::account( ACCOUNT_2_PUBLIC_KEY.clone(), account_2_balance, @@ -64,7 +64,7 @@ static GENESIS_CUSTOM_ACCOUNTS: Lazy> = Lazy::new(|| { fn should_run_genesis() { let protocol_version = ProtocolVersion::V1_0_0; - let run_genesis_request = ChainspecConfig::create_genesis_request_from_production_chainspec( + let run_genesis_request = ChainspecConfig::create_genesis_request_from_local_chainspec( GENESIS_CUSTOM_ACCOUNTS.clone(), protocol_version, ) @@ -121,15 +121,13 @@ fn should_track_total_token_supply_in_mint() { let accounts = GENESIS_CUSTOM_ACCOUNTS.clone(); let wasm_config = *DEFAULT_WASM_CONFIG; let system_config = *DEFAULT_SYSTEM_CONFIG; - let protocol_version = ProtocolVersion::V1_0_0; + let protocol_version = DEFAULT_PROTOCOL_VERSION; let validator_slots = DEFAULT_VALIDATOR_SLOTS; let auction_delay = DEFAULT_AUCTION_DELAY; let locked_funds_period = DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS; let round_seigniorage_rate = DEFAULT_ROUND_SEIGNIORAGE_RATE; let unbonding_delay = DEFAULT_UNBONDING_DELAY; let genesis_timestamp = DEFAULT_GENESIS_TIMESTAMP_MILLIS; - let refund_handling = DEFAULT_REFUND_HANDLING; - let fee_handling = DEFAULT_FEE_HANDLING; let config = GenesisConfigBuilder::default() .with_accounts(accounts.clone()) .with_wasm_config(wasm_config) @@ -140,8 +138,6 @@ fn should_track_total_token_supply_in_mint() { .with_round_seigniorage_rate(round_seigniorage_rate) .with_unbonding_delay(unbonding_delay) .with_genesis_timestamp_millis(genesis_timestamp) - .with_refund_handling(refund_handling) - .with_fee_handling(fee_handling) .build(); let genesis_request = GenesisRequest::new( @@ -155,7 +151,7 @@ fn should_track_total_token_supply_in_mint() { builder.run_genesis(genesis_request); - let total_supply = builder.total_supply(None); + let total_supply = builder.total_supply(None, protocol_version); let expected_balance: U512 = accounts.iter().map(|item| item.balance().value()).sum(); let expected_staked_amount: U512 = accounts diff --git a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/finalize_payment.rs b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/finalize_payment.rs index ba3ca5cd22..bee2c2a74d 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/finalize_payment.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/finalize_payment.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, SYSTEM_ADDR, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, SYSTEM_ADDR, }; use casper_types::{ account::AccountHash, runtime_args, system::handle_payment, Key, RuntimeArgs, URef, U512, @@ -41,7 +41,7 @@ fn initialize() -> LmdbWasmTestBuilder { ) .build(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder.exec(exec_request_1).expect_success().commit(); @@ -79,7 +79,8 @@ fn finalize_payment_should_not_be_run_by_non_system_accounts() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn finalize_payment_should_refund_to_specified_purse() { let mut builder = LmdbWasmTestBuilder::default(); let payment_amount = *DEFAULT_PAYMENT; @@ -94,7 +95,7 @@ fn finalize_payment_should_refund_to_specified_purse() { ARG_PURSE_NAME => LOCAL_REFUND_PURSE, }; - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let create_purse_request = { ExecuteRequestBuilder::standard( @@ -125,19 +126,17 @@ fn finalize_payment_should_refund_to_specified_purse() { "payment purse should start with zero balance" ); - let exec_request = { - let genesis_account_hash = *DEFAULT_ACCOUNT_ADDR; + let genesis_account_hash = *DEFAULT_ACCOUNT_ADDR; - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_deploy_hash([1; 32]) - .with_session_code("do_nothing.wasm", RuntimeArgs::default()) - .with_payment_code(FINALIZE_PAYMENT, args) - .with_authorization_keys(&[genesis_account_hash]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_deploy_hash([1; 32]) + .with_session_code("do_nothing.wasm", RuntimeArgs::default()) + .with_payment_code(FINALIZE_PAYMENT, args) + .with_authorization_keys(&[genesis_account_hash]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); diff --git a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/get_payment_purse.rs b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/get_payment_purse.rs index fe5b143ca9..4b5219067b 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/get_payment_purse.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/get_payment_purse.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{account::AccountHash, runtime_args, U512}; @@ -12,7 +12,8 @@ const ARG_AMOUNT: &str = "amount"; const ARG_TARGET: &str = "target"; #[ignore] -#[test] +#[allow(unused)] +//#[test] fn should_run_get_payment_purse_contract_default_account() { let exec_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -23,14 +24,15 @@ fn should_run_get_payment_purse_contract_default_account() { ) .build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit(); } #[ignore] -#[test] +#[allow(unused)] +//#[test] fn should_run_get_payment_purse_contract_account_1() { let exec_request_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -47,7 +49,7 @@ fn should_run_get_payment_purse_contract_account_1() { ) .build(); LmdbWasmTestBuilder::default() - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request_1) .expect_success() .commit() diff --git a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/refund_purse.rs b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/refund_purse.rs index a1b6844725..494be66035 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/handle_payment/refund_purse.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/handle_payment/refund_purse.rs @@ -1,6 +1,6 @@ use casper_engine_test_support::{ DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_PAYMENT, MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{account::AccountHash, runtime_args, system::mint, RuntimeArgs, U512}; @@ -36,7 +36,7 @@ fn should_run_refund_purse_contract_account_1() { fn initialize() -> LmdbWasmTestBuilder { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); builder } @@ -89,25 +89,23 @@ fn refund_tests(builder: &mut LmdbWasmTestBuilder, account_hash: AccountHash) { .expect_success() .commit(); - let refund_purse_request = { - let deploy = DeployItemBuilder::new() - .with_address(account_hash) - .with_deploy_hash([2; 32]) - .with_session_code("do_nothing.wasm", RuntimeArgs::default()) - .with_payment_code( - "refund_purse.wasm", - runtime_args! { - ARG_PAYMENT_AMOUNT => *DEFAULT_PAYMENT, - mint::ARG_AMOUNT => *DEFAULT_PAYMENT, - ARG_PURSE_NAME_1 => LOCAL_REFUND_PURSE_1, - ARG_PURSE_NAME_2 => LOCAL_REFUND_PURSE_2, - }, - ) - .with_authorization_keys(&[account_hash]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(account_hash) + .with_deploy_hash([2; 32]) + .with_session_code("do_nothing.wasm", RuntimeArgs::default()) + .with_payment_code( + "refund_purse.wasm", + runtime_args! { + ARG_PAYMENT_AMOUNT => *DEFAULT_PAYMENT, + mint::ARG_AMOUNT => *DEFAULT_PAYMENT, + ARG_PURSE_NAME_1 => LOCAL_REFUND_PURSE_1, + ARG_PURSE_NAME_2 => LOCAL_REFUND_PURSE_2, + }, + ) + .with_authorization_keys(&[account_hash]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let refund_purse_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); builder.exec(refund_purse_request).expect_success().commit(); } diff --git a/execution_engine_testing/tests/src/test/system_contracts/standard_payment.rs b/execution_engine_testing/tests/src/test/system_contracts/standard_payment.rs index 353a93503c..78c7d31fdc 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/standard_payment.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/standard_payment.rs @@ -3,9 +3,9 @@ use std::collections::HashMap; use assert_matches::assert_matches; use casper_engine_test_support::{ - utils, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, + DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_ACCOUNT_KEY, DEFAULT_GAS_PRICE, DEFAULT_PAYMENT, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{ engine_state::{Error, MAX_PAYMENT}, @@ -25,7 +25,8 @@ const ARG_AMOUNT: &str = "amount"; const ARG_TARGET: &str = "target"; #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_raise_insufficient_payment_when_caller_lacks_minimum_balance() { let account_1_account_hash = ACCOUNT_1_ADDR; @@ -34,12 +35,12 @@ fn should_raise_insufficient_payment_when_caller_lacks_minimum_balance() { TRANSFER_PURSE_TO_ACCOUNT_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => *MAX_PAYMENT - U512::one() }, ) - .build(); + .build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .expect_success() .commit() @@ -50,16 +51,14 @@ fn should_raise_insufficient_payment_when_caller_lacks_minimum_balance() { ExecuteRequestBuilder::standard(ACCOUNT_1_ADDR, REVERT_WASM, RuntimeArgs::default()) .build(); - let account_1_response = builder + let error_message = builder .exec(account_1_request) .commit() - .get_exec_result_owned(1) + .get_error_message() .expect("there should be a response"); - let error_message = utils::get_error_message(account_1_response); - assert!( - error_message.contains("InsufficientPayment"), + error_message.contains("Insufficient payment"), "expected insufficient payment, got: {}", error_message ); @@ -75,29 +74,28 @@ fn should_raise_insufficient_payment_when_caller_lacks_minimum_balance() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_forward_payment_execution_runtime_error() { let account_1_account_hash = ACCOUNT_1_ADDR; let transferred_amount = U512::from(1); - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) .with_payment_code(REVERT_WASM, RuntimeArgs::default()) .with_session_code( TRANSFER_PURSE_TO_ACCOUNT_WASM, - runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => transferred_amount } + runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => transferred_amount }, ) .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); @@ -131,39 +129,37 @@ fn should_forward_payment_execution_runtime_error() { "no net resources should be gained or lost post-distribution" ); - let response = builder + let exec_result = builder .get_exec_result_owned(0) .expect("there should be a response"); - let execution_result = utils::get_success_result(&response); - let error = execution_result.as_error().expect("should have error"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::Revert(ApiError::User(100)))); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_forward_payment_execution_gas_limit_error() { let account_1_account_hash = ACCOUNT_1_ADDR; let transferred_amount = U512::from(1); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) .with_payment_code(ENDLESS_LOOP_WASM, RuntimeArgs::default()) .with_session_code( TRANSFER_PURSE_TO_ACCOUNT_WASM, - runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => transferred_amount } + runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => transferred_amount }, ) .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); @@ -197,34 +193,33 @@ fn should_forward_payment_execution_gas_limit_error() { "no net resources should be gained or lost post-distribution" ); - let response = builder + let exec_result = builder .get_exec_result_owned(0) .expect("there should be a response"); - let execution_result = utils::get_success_result(&response); - let error = execution_result.as_error().expect("should have error"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::GasLimit)); let payment_gas_limit = Gas::from_motes(Motes::new(*MAX_PAYMENT), DEFAULT_GAS_PRICE) .expect("should convert to gas"); assert_eq!( - execution_result.cost(), + exec_result.consumed(), payment_gas_limit, "cost should equal gas limit" ); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_run_out_of_gas_when_session_code_exceeds_gas_limit() { let account_1_account_hash = ACCOUNT_1_ADDR; let payment_purse_amount = *DEFAULT_PAYMENT; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) .with_session_code( ENDLESS_LOOP_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => U512::from(transferred_amount) }, @@ -232,53 +227,50 @@ fn should_run_out_of_gas_when_session_code_exceeds_gas_limit() { .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); - let response = builder + let exec_result = builder .get_exec_result_owned(0) .expect("there should be a response"); - let execution_result = utils::get_success_result(&response); - let error = execution_result.as_error().expect("should have error"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::GasLimit)); let session_gas_limit = Gas::from_motes(Motes::new(payment_purse_amount), DEFAULT_GAS_PRICE) .expect("should convert to gas"); assert_eq!( - execution_result.cost(), + exec_result.consumed(), session_gas_limit, "cost should equal gas limit" ); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_correctly_charge_when_session_code_runs_out_of_gas() { let payment_purse_amount = *DEFAULT_PAYMENT; - let exec_request = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_deploy_hash([1; 32]) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) - .with_session_code(ENDLESS_LOOP_WASM, RuntimeArgs::default()) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .build(); + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_deploy_hash([1; 32]) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_session_code(ENDLESS_LOOP_WASM, RuntimeArgs::default()) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(exec_request) .commit(); @@ -293,12 +285,11 @@ fn should_correctly_charge_when_session_code_runs_out_of_gas() { "balance should be less than initial balance" ); - let response = builder + let exec_result = builder .get_exec_result_owned(0) .expect("there should be a response"); - let success_result = utils::get_success_result(&response); - let gas = success_result.cost(); + let gas = exec_result.consumed(); let motes = Motes::from_gas(gas, DEFAULT_GAS_PRICE).expect("should have motes"); let tally = motes.value() + modified_balance; @@ -308,30 +299,29 @@ fn should_correctly_charge_when_session_code_runs_out_of_gas() { "no net resources should be gained or lost post-distribution" ); - let execution_result = utils::get_success_result(&response); - let error = execution_result.as_error().expect("should have error"); + let error = exec_result.error().expect("should have error"); assert_matches!(error, Error::Exec(ExecError::GasLimit)); let session_gas_limit = Gas::from_motes(Motes::new(payment_purse_amount), DEFAULT_GAS_PRICE) .expect("should convert to gas"); assert_eq!( - execution_result.cost(), + exec_result.consumed(), session_gas_limit, "cost should equal gas limit" ); } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_correctly_charge_when_session_code_fails() { let account_1_account_hash = ACCOUNT_1_ADDR; let payment_purse_amount = *DEFAULT_PAYMENT; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) .with_session_code( REVERT_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => U512::from(transferred_amount) }, @@ -339,12 +329,11 @@ fn should_correctly_charge_when_session_code_fails() { .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); @@ -371,30 +360,29 @@ fn should_correctly_charge_when_session_code_fails() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_correctly_charge_when_session_code_succeeds() { let account_1_account_hash = ACCOUNT_1_ADDR; let payment_purse_amount = *DEFAULT_PAYMENT; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_deploy_hash([1; 32]) .with_session_code( TRANSFER_PURSE_TO_ACCOUNT_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => U512::from(transferred_amount) }, ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let proposer_reward_starting_balance_1 = builder.get_proposer_purse_balance(); @@ -428,30 +416,29 @@ fn should_correctly_charge_when_session_code_succeeds() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn should_finalize_to_rewards_purse() { let account_1_account_hash = ACCOUNT_1_ADDR; let payment_purse_amount = *DEFAULT_PAYMENT; let transferred_amount = 1; - let exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code( TRANSFER_PURSE_TO_ACCOUNT_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => U512::from(transferred_amount) }, ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .with_deploy_hash([1; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let proposer_reward_starting_balance = builder.get_proposer_purse_balance(); @@ -466,7 +453,8 @@ fn should_finalize_to_rewards_purse() { } #[ignore] -#[test] +#[allow(unused)] +// #[test] fn independent_standard_payments_should_not_write_the_same_keys() { let account_1_account_hash = ACCOUNT_1_ADDR; let payment_purse_amount = *DEFAULT_PAYMENT; @@ -474,51 +462,45 @@ fn independent_standard_payments_should_not_write_the_same_keys() { let mut builder = LmdbWasmTestBuilder::default(); - let setup_exec_request = { - let deploy = DeployItemBuilder::new() + let deploy_item = DeployItemBuilder::new() .with_address(*DEFAULT_ACCOUNT_ADDR) .with_session_code( TRANSFER_PURSE_TO_ACCOUNT_WASM, runtime_args! { ARG_TARGET => account_1_account_hash, ARG_AMOUNT => U512::from(transfer_amount) }, ) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) .with_deploy_hash([1; 32]) .build(); - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let setup_exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); // create another account via transfer builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(setup_exec_request) .expect_success() .commit(); - let exec_request_from_genesis = { - let deploy = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) - .with_deploy_hash([2; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; - - let exec_request_from_account_1 = { - let deploy = DeployItemBuilder::new() - .with_address(ACCOUNT_1_ADDR) - .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => payment_purse_amount }) - .with_authorization_keys(&[account_1_account_hash]) - .with_deploy_hash([1; 32]) - .build(); - - ExecuteRequestBuilder::new().push_deploy(deploy).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_KEY]) + .with_deploy_hash([2; 32]) + .build(); + + let exec_request_from_genesis = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); + + let deploy_item = DeployItemBuilder::new() + .with_address(ACCOUNT_1_ADDR) + .with_session_code(DO_NOTHING_WASM, RuntimeArgs::default()) + .with_standard_payment(runtime_args! { ARG_AMOUNT => payment_purse_amount }) + .with_authorization_keys(&[account_1_account_hash]) + .with_deploy_hash([1; 32]) + .build(); + + let exec_request_from_account_1 = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); // run two independent deploys builder diff --git a/execution_engine_testing/tests/src/test/system_contracts/upgrade.rs b/execution_engine_testing/tests/src/test/system_contracts/upgrade.rs index 71f35eac68..1e4296a99c 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/upgrade.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/upgrade.rs @@ -5,10 +5,10 @@ use num_rational::Ratio; use casper_engine_test_support::{ ChainspecConfig, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, DEFAULT_MAX_ASSOCIATED_KEYS, DEFAULT_UNBONDING_DELAY, - PRODUCTION_RUN_GENESIS_REQUEST, + LOCAL_GENESIS_REQUEST, }; -use crate::{lmdb_fixture, lmdb_fixture::CONTRACT_REGISTRY_SPECIAL_ADDRESS}; +use crate::{lmdb_fixture, lmdb_fixture::ENTRY_REGISTRY_SPECIAL_ADDRESS}; use casper_types::{ account::{AccountHash, ACCOUNT_HASH_LENGTH}, runtime_args, system, @@ -25,62 +25,13 @@ use casper_types::{ const PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::V1_0_0; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); const ARG_ACCOUNT: &str = "account"; -// -// fn get_upgraded_wasm_config() -> WasmConfig { -// let opcode_cost = OpcodeCosts { -// bit: DEFAULT_BIT_COST + 1, -// add: DEFAULT_ADD_COST + 1, -// mul: DEFAULT_MUL_COST + 1, -// div: DEFAULT_DIV_COST + 1, -// load: DEFAULT_LOAD_COST + 1, -// store: DEFAULT_STORE_COST + 1, -// op_const: DEFAULT_CONST_COST + 1, -// local: DEFAULT_LOCAL_COST + 1, -// global: DEFAULT_GLOBAL_COST + 1, -// control_flow: ControlFlowCosts { -// block: DEFAULT_CONTROL_FLOW_BLOCK_OPCODE + 1, -// op_loop: DEFAULT_CONTROL_FLOW_LOOP_OPCODE + 1, -// op_if: DEFAULT_CONTROL_FLOW_IF_OPCODE + 1, -// op_else: DEFAULT_CONTROL_FLOW_ELSE_OPCODE + 1, -// end: DEFAULT_CONTROL_FLOW_END_OPCODE + 1, -// br: DEFAULT_CONTROL_FLOW_BR_OPCODE + 1, -// br_if: DEFAULT_CONTROL_FLOW_BR_IF_OPCODE + 1, -// br_table: BrTableCost { -// cost: DEFAULT_CONTROL_FLOW_BR_TABLE_OPCODE + 1, -// size_multiplier: DEFAULT_CONTROL_FLOW_BR_TABLE_MULTIPLIER + 1, -// }, -// op_return: DEFAULT_CONTROL_FLOW_RETURN_OPCODE + 1, -// call: DEFAULT_CONTROL_FLOW_CALL_OPCODE + 1, -// call_indirect: DEFAULT_CONTROL_FLOW_CALL_INDIRECT_OPCODE + 1, -// drop: DEFAULT_CONTROL_FLOW_DROP_OPCODE + 1, -// select: DEFAULT_CONTROL_FLOW_SELECT_OPCODE + 1, -// }, -// integer_comparison: DEFAULT_INTEGER_COMPARISON_COST + 1, -// conversion: DEFAULT_CONVERSION_COST + 1, -// unreachable: DEFAULT_UNREACHABLE_COST + 1, -// nop: DEFAULT_NOP_COST + 1, -// current_memory: DEFAULT_CURRENT_MEMORY_COST + 1, -// grow_memory: DEFAULT_GROW_MEMORY_COST + 1, -// }; -// let storage_costs = StorageCosts::default(); -// let host_function_costs = HostFunctionCosts::default(); -// let messages_limits = MessageLimits::default(); -// WasmConfig::new( -// DEFAULT_WASM_MAX_MEMORY, -// DEFAULT_MAX_STACK_HEIGHT * 2, -// opcode_cost, -// storage_costs, -// host_function_costs, -// messages_limits, -// ) -// } #[ignore] #[test] fn should_upgrade_only_protocol_version() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // let old_wasm_config = *builder.get_engine_state().config().wasm_config(); @@ -114,7 +65,7 @@ fn should_upgrade_only_protocol_version() { fn should_allow_only_wasm_costs_patch_version() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -148,7 +99,7 @@ fn should_allow_only_wasm_costs_patch_version() { fn should_allow_only_wasm_costs_minor_version() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -186,7 +137,7 @@ fn should_allow_only_wasm_costs_minor_version() { fn should_not_downgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // let old_wasm_config = *builder.get_engine_state().config().wasm_config(); @@ -228,7 +179,7 @@ fn should_not_downgrade() { fn should_not_skip_major_versions() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); @@ -255,7 +206,7 @@ fn should_not_skip_major_versions() { fn should_allow_skip_minor_versions() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); @@ -283,7 +234,7 @@ fn should_allow_skip_minor_versions() { fn should_upgrade_only_validator_slots() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -340,7 +291,7 @@ fn should_upgrade_only_validator_slots() { fn should_upgrade_only_auction_delay() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -397,7 +348,7 @@ fn should_upgrade_only_auction_delay() { fn should_upgrade_only_locked_funds_period() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -454,7 +405,7 @@ fn should_upgrade_only_locked_funds_period() { fn should_upgrade_only_round_seigniorage_rate() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -515,7 +466,7 @@ fn should_upgrade_only_round_seigniorage_rate() { fn should_upgrade_only_unbonding_delay() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -574,7 +525,7 @@ fn should_upgrade_only_unbonding_delay() { fn should_apply_global_state_upgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -640,7 +591,7 @@ fn should_apply_global_state_upgrade() { fn should_increase_max_associated_keys_after_upgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let sem_ver = PROTOCOL_VERSION.value(); let new_protocol_version = @@ -685,7 +636,6 @@ fn should_increase_max_associated_keys_after_upgrade() { ARG_ACCOUNT => account_hash, }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(add_request).expect_success().commit(); @@ -708,10 +658,10 @@ fn should_correctly_migrate_and_prune_system_contract_records() { let (mut builder, lmdb_fixture_state, _temp_dir) = lmdb_fixture::builder_from_global_state_fixture(lmdb_fixture::RELEASE_1_3_1); - let legacy_system_contract_registry = { + let legacy_system_entity_registry = { let stored_value: StoredValue = builder - .query(None, CONTRACT_REGISTRY_SPECIAL_ADDRESS, &[]) - .expect("should query system contract registry"); + .query(None, ENTRY_REGISTRY_SPECIAL_ADDRESS, &[]) + .expect("should query system entity registry"); let cl_value = stored_value .as_cl_value() .cloned() @@ -725,7 +675,7 @@ fn should_correctly_migrate_and_prune_system_contract_records() { let mut global_state_update = BTreeMap::::new(); - let registry = CLValue::from_t(legacy_system_contract_registry.clone()) + let registry = CLValue::from_t(legacy_system_entity_registry.clone()) .expect("must convert to StoredValue") .into(); @@ -745,7 +695,7 @@ fn should_correctly_migrate_and_prune_system_contract_records() { let system_names = vec![system::MINT, system::AUCTION, system::HANDLE_PAYMENT]; for name in system_names { - let legacy_hash = *legacy_system_contract_registry + let legacy_hash = *legacy_system_entity_registry .get(name) .expect("must have hash"); let legacy_contract_key = Key::Hash(legacy_hash.value()); diff --git a/execution_engine_testing/tests/src/test/system_costs.rs b/execution_engine_testing/tests/src/test/system_costs.rs index 5fa286fc23..6952baa797 100644 --- a/execution_engine_testing/tests/src/test/system_costs.rs +++ b/execution_engine_testing/tests/src/test/system_costs.rs @@ -5,8 +5,8 @@ use casper_engine_test_support::{ utils, ChainspecConfig, DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNTS, DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_INITIAL_BALANCE, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_MAX_ASSOCIATED_KEYS, DEFAULT_MINIMUM_DELEGATION_AMOUNT, - DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, MINIMUM_ACCOUNT_CREATION_BALANCE, - PRODUCTION_RUN_GENESIS_REQUEST, + DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, + MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_types::{ runtime_args, @@ -18,8 +18,7 @@ use casper_types::{ GenesisValidator, HandlePaymentCosts, HostFunction, HostFunctionCost, HostFunctionCosts, MessageLimits, MintCosts, Motes, OpcodeCosts, ProtocolVersion, PublicKey, RuntimeArgs, SecretKey, StandardPaymentCosts, StorageCosts, SystemConfig, WasmConfig, DEFAULT_ADD_BID_COST, - DEFAULT_INSTALL_UPGRADE_GAS_LIMIT, DEFAULT_MAX_STACK_HEIGHT, - DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT, DEFAULT_WASM_MAX_MEMORY, U512, + DEFAULT_MAX_STACK_HEIGHT, DEFAULT_WASM_MAX_MEMORY, U512, }; use crate::wasm_utils; @@ -43,18 +42,16 @@ const UPDATED_CALL_CONTRACT_COST: HostFunctionCost = 12_345; const NEW_ADD_BID_COST: u32 = 2_500_000_000; const NEW_WITHDRAW_BID_COST: u32 = 2_500_000_000; const NEW_DELEGATE_COST: u32 = 2_500_000_000; -const NEW_UNDELEGATE_COST: u32 = 2_500_000_000; -const NEW_REDELEGATE_COST: u32 = 2_500_000_000; +const NEW_UNDELEGATE_COST: u32 = NEW_DELEGATE_COST; +const NEW_REDELEGATE_COST: u32 = NEW_DELEGATE_COST; const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); -static OLD_PROTOCOL_VERSION: Lazy = Lazy::new(|| *DEFAULT_PROTOCOL_VERSION); -static NEW_PROTOCOL_VERSION: Lazy = Lazy::new(|| { - ProtocolVersion::from_parts( - OLD_PROTOCOL_VERSION.value().major, - OLD_PROTOCOL_VERSION.value().minor, - OLD_PROTOCOL_VERSION.value().patch + 1, - ) -}); +const OLD_PROTOCOL_VERSION: ProtocolVersion = DEFAULT_PROTOCOL_VERSION; +const NEW_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts( + OLD_PROTOCOL_VERSION.value().major, + OLD_PROTOCOL_VERSION.value().minor, + OLD_PROTOCOL_VERSION.value().patch + 1, +); const ARG_PURSE_NAME: &str = "purse_name"; const NAMED_PURSE_NAME: &str = "purse_1"; @@ -65,7 +62,7 @@ const ARG_AMOUNT: &str = "amount"; fn add_bid_and_withdraw_bid_have_expected_costs() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let system_contract_hashes_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -157,12 +154,12 @@ fn add_bid_and_withdraw_bid_have_expected_costs() { #[test] fn upgraded_add_bid_and_withdraw_bid_have_expected_costs() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build() }; @@ -174,7 +171,6 @@ fn upgraded_add_bid_and_withdraw_bid_have_expected_costs() { SYSTEM_CONTRACT_HASHES_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder .exec(system_contract_hashes_request) @@ -201,7 +197,6 @@ fn upgraded_add_bid_and_withdraw_bid_have_expected_costs() { auction::ARG_DELEGATION_RATE => BID_DELEGATION_RATE, }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let balance_before = builder.get_purse_balance(account.main_purse()); @@ -238,7 +233,6 @@ fn upgraded_add_bid_and_withdraw_bid_have_expected_costs() { auction::ARG_AMOUNT => U512::from(BOND_AMOUNT), }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let balance_before = builder.get_purse_balance(account.main_purse()); @@ -263,17 +257,17 @@ fn delegate_and_undelegate_have_expected_costs() { let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let validator_2 = GenesisAccount::account( VALIDATOR_2.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); @@ -407,17 +401,17 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { let accounts = { let validator_1 = GenesisAccount::account( VALIDATOR_1.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); let validator_2 = GenesisAccount::account( VALIDATOR_2.clone(), - Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE.into()), + Motes::new(DEFAULT_ACCOUNT_INITIAL_BALANCE), Some(GenesisValidator::new( - Motes::new(VALIDATOR_1_STAKE.into()), + Motes::new(VALIDATOR_1_STAKE), DelegationRate::zero(), )), ); @@ -434,8 +428,8 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build() }; @@ -447,7 +441,6 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { SYSTEM_CONTRACT_HASHES_NAME, RuntimeArgs::default(), ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder .exec(system_contract_hashes_request) @@ -474,7 +467,6 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { auction::ARG_AMOUNT => U512::from(BID_AMOUNT), }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let proposer_reward_starting_balance_1 = builder.get_proposer_purse_balance(); @@ -491,6 +483,7 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { balance_after, balance_before - U512::from(BID_AMOUNT) - transaction_fee_1, ); + assert_eq!(builder.last_exec_gas_cost().value(), call_cost); // Redelegate bid @@ -511,7 +504,6 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { auction::ARG_NEW_VALIDATOR => VALIDATOR_2.clone() }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); builder.exec(redelegate_request).expect_success().commit(); @@ -536,7 +528,6 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { auction::ARG_AMOUNT => U512::from(BID_AMOUNT - DEFAULT_MINIMUM_DELEGATION_AMOUNT), }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); let balance_before = builder.get_purse_balance(account.main_purse()); @@ -559,7 +550,7 @@ fn upgraded_delegate_and_undelegate_have_expected_costs() { fn mint_transfer_has_expected_costs() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let transfer_request_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -627,7 +618,7 @@ fn mint_transfer_has_expected_costs() { fn should_charge_for_erroneous_system_contract_calls() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let auction_hash = builder.get_auction_contract_hash(); let mint_hash = builder.get_mint_contract_hash(); @@ -706,11 +697,11 @@ fn should_charge_for_erroneous_system_contract_calls() { handle_payment::METHOD_SET_REFUND_PURSE, system_config.handle_payment_costs().set_refund_purse, ), - ( - handle_payment_hash, - handle_payment::METHOD_FINALIZE_PAYMENT, - system_config.handle_payment_costs().finalize_payment, - ), + // ( + // handle_payment_hash, + // handle_payment::METHOD_FINALIZE_PAYMENT, + // system_config.handle_payment_costs().finalize_payment, + // ), ]; for (contract_hash, entrypoint, expected_cost) in entrypoint_calls { @@ -731,9 +722,7 @@ fn should_charge_for_erroneous_system_contract_calls() { let _error = builder .get_last_exec_result() .expect("should have results") - .get(0) - .expect("should have first result") - .as_error() + .error() .unwrap_or_else(|| panic!("should have error while executing {}", entrypoint)); let transaction_fee = @@ -749,7 +738,12 @@ fn should_charge_for_erroneous_system_contract_calls() { entrypoint, expected_cost, ); - assert_eq!(builder.last_exec_gas_cost().value(), call_cost); + assert_eq!( + builder.last_exec_gas_cost().value(), + call_cost, + "{:?}", + entrypoint + ); } } @@ -758,25 +752,23 @@ fn should_charge_for_erroneous_system_contract_calls() { fn should_verify_do_nothing_charges_only_for_standard_payment() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) .expect("should have default account"); - let do_nothing_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) - .with_empty_payment_bytes(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let deploy_item = DeployItemBuilder::new() + .with_address(*DEFAULT_ACCOUNT_ADDR) + .with_session_bytes(wasm_utils::do_nothing_bytes(), RuntimeArgs::default()) + .with_standard_payment(runtime_args! { + ARG_AMOUNT => *DEFAULT_PAYMENT + }) + .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) + .with_deploy_hash([42; 32]) + .build(); + + let do_nothing_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); let user_funds_before = builder.get_purse_balance(default_account.main_purse()); @@ -798,7 +790,7 @@ fn should_verify_do_nothing_charges_only_for_standard_payment() { fn should_verify_wasm_add_bid_wasm_cost_is_not_recursive() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let new_opcode_costs = OpcodeCosts { bit: 0, @@ -864,8 +856,8 @@ fn should_verify_wasm_add_bid_wasm_cost_is_not_recursive() { let new_handle_payment_costs = HandlePaymentCosts::default(); let system_costs_config = SystemConfig::new( - DEFAULT_INSTALL_UPGRADE_GAS_LIMIT, - DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT, + SystemConfig::default().install_upgrade_limit(), + SystemConfig::default().standard_transaction_limit(), new_auction_costs, new_mint_costs, new_handle_payment_costs, @@ -886,8 +878,8 @@ fn should_verify_wasm_add_bid_wasm_cost_is_not_recursive() { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*OLD_PROTOCOL_VERSION) - .with_new_protocol_version(*NEW_PROTOCOL_VERSION) + .with_current_protocol_version(OLD_PROTOCOL_VERSION) + .with_new_protocol_version(NEW_PROTOCOL_VERSION) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build() }; @@ -907,7 +899,6 @@ fn should_verify_wasm_add_bid_wasm_cost_is_not_recursive() { auction::ARG_DELEGATION_RATE => BID_DELEGATION_RATE, }, ) - .with_protocol_version(*NEW_PROTOCOL_VERSION) .build(); // Verify that user is called and deploy raises runtime error diff --git a/execution_engine_testing/tests/src/test/tutorial/counter.rs b/execution_engine_testing/tests/src/test/tutorial/counter.rs index fdcb3d7364..b7ac5c1ea7 100644 --- a/execution_engine_testing/tests/src/test/tutorial/counter.rs +++ b/execution_engine_testing/tests/src/test/tutorial/counter.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{Key, RuntimeArgs, StoredValue}; @@ -13,7 +12,7 @@ const COUNTER_KEY: &str = "counter"; #[test] fn should_run_counter_example() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_request_1 = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, diff --git a/execution_engine_testing/tests/src/test/tutorial/hello_world.rs b/execution_engine_testing/tests/src/test/tutorial/hello_world.rs index 6b81358c1d..a25c7ed62a 100644 --- a/execution_engine_testing/tests/src/test/tutorial/hello_world.rs +++ b/execution_engine_testing/tests/src/test/tutorial/hello_world.rs @@ -1,6 +1,5 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, Key, StoredValue}; @@ -13,7 +12,7 @@ const MESSAGE_VALUE: &str = "Hello, world!"; #[test] fn should_run_hello_world() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let exec_request = { let session_args = runtime_args! { diff --git a/execution_engine_testing/tests/src/test/upgrade.rs b/execution_engine_testing/tests/src/test/upgrade.rs index c77122cf40..54e93da8af 100644 --- a/execution_engine_testing/tests/src/test/upgrade.rs +++ b/execution_engine_testing/tests/src/test/upgrade.rs @@ -1,16 +1,14 @@ use casper_engine_test_support::{ - ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, DEFAULT_ACCOUNT_ADDR, - MINIMUM_ACCOUNT_CREATION_BALANCE, PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, UpgradeRequestBuilder, + DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, MINIMUM_ACCOUNT_CREATION_BALANCE, }; use casper_execution_engine::{engine_state, execution::ExecError}; use casper_types::{ account::AccountHash, addressable_entity::{AssociatedKeys, Weight}, - package::{EntityVersion, ENTITY_INITIAL_VERSION}, - runtime_args, - system::mint, - AddressableEntityHash, CLValue, EraId, PackageHash, ProtocolVersion, RuntimeArgs, StoredValue, + runtime_args, AddressableEntityHash, CLValue, EntityVersion, EraId, PackageHash, + ProtocolVersion, RuntimeArgs, StoredValue, ENTITY_INITIAL_VERSION, }; const DO_NOTHING_STORED_CONTRACT_NAME: &str = "do_nothing_stored"; @@ -50,7 +48,7 @@ const ARG_IS_LOCKED: &str = "is_locked"; fn should_upgrade_do_nothing_to_do_something_version_hash_call() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Create contract package and store contract ver: 1.0.0 with "delegate" entry function { @@ -164,7 +162,7 @@ fn should_upgrade_do_nothing_to_do_something_version_hash_call() { fn should_upgrade_do_nothing_to_do_something_contract_call() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // Create contract package and store contract ver: 1.0.0 { @@ -298,7 +296,7 @@ fn should_upgrade_do_nothing_to_do_something_contract_call() { fn should_be_able_to_observe_state_transition_across_upgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store do-nothing-stored { @@ -397,7 +395,7 @@ fn should_be_able_to_observe_state_transition_across_upgrade() { fn should_support_extending_functionality() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store do-nothing-stored { @@ -540,7 +538,7 @@ fn should_support_extending_functionality() { fn should_maintain_named_keys_across_upgrade() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store contract { @@ -644,7 +642,7 @@ fn should_maintain_named_keys_across_upgrade() { fn should_fail_upgrade_for_locked_contract() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); // store contract { @@ -715,7 +713,7 @@ fn should_only_upgrade_if_threshold_is_met() { let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let install_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -825,14 +823,14 @@ fn should_only_upgrade_if_threshold_is_met() { entity_account_hashes }; - let valid_upgrade_request = ExecuteRequestBuilder::with_authorization_keys( + let valid_upgrade_request = ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, UPGRADE_THRESHOLD_UPGRADER, runtime_args! { ARG_CONTRACT_PACKAGE => upgrade_threshold_package_hash }, - &authorization_keys, ) + .with_authorization_keys(authorization_keys.into_iter().collect()) .build(); builder @@ -841,7 +839,7 @@ fn should_only_upgrade_if_threshold_is_met() { .commit(); } -fn setup_upgrade_threshold_state() -> (LmdbWasmTestBuilder, ProtocolVersion, AccountHash) { +fn setup_upgrade_threshold_state() -> (LmdbWasmTestBuilder, AccountHash) { const ACCOUNT_1_ADDR: AccountHash = AccountHash::new([1u8; 32]); const UPGRADE_THRESHOLDS_FIXTURE: &str = "upgrade_thresholds"; @@ -865,26 +863,19 @@ fn setup_upgrade_threshold_state() -> (LmdbWasmTestBuilder, ProtocolVersion, Acc .upgrade_using_scratch(&mut upgrade_request) .expect_upgrade_success(); - let transfer = ExecuteRequestBuilder::transfer( - *DEFAULT_ACCOUNT_ADDR, - runtime_args! { - mint::ARG_TARGET => ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => MINIMUM_ACCOUNT_CREATION_BALANCE, - mint::ARG_ID => Some(42u64), - }, - ) - .with_protocol_version(new_protocol_version) - .build(); + let transfer = TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, ACCOUNT_1_ADDR) + .with_transfer_id(42) + .build(); - builder.exec(transfer).expect_success().commit(); + builder.transfer_and_commit(transfer).expect_success(); - (builder, new_protocol_version, ACCOUNT_1_ADDR) + (builder, ACCOUNT_1_ADDR) } #[ignore] #[test] fn should_migrate_with_correct_upgrade_thresholds() { - let (mut builder, new_protocol_version, _) = setup_upgrade_threshold_state(); + let (mut builder, _) = setup_upgrade_threshold_state(); let default_addressable_entity = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -905,7 +896,6 @@ fn should_migrate_with_correct_upgrade_thresholds() { HASH_KEY_NAME => contract_hash }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(exec_request).expect_success().commit(); let purse_holder_as_entity = builder @@ -922,7 +912,7 @@ fn should_migrate_with_correct_upgrade_thresholds() { #[ignore] #[test] fn should_correctly_set_upgrade_threshold_on_entity_upgrade() { - let (mut builder, new_protocol_version, entity_1) = setup_upgrade_threshold_state(); + let (mut builder, entity_1) = setup_upgrade_threshold_state(); let default_addressable_entity = builder .get_entity_with_named_keys_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -952,7 +942,6 @@ fn should_correctly_set_upgrade_threshold_on_entity_upgrade() { HASH_KEY_NAME => entity_hash }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(exec_request).expect_success().commit(); @@ -972,7 +961,6 @@ fn should_correctly_set_upgrade_threshold_on_entity_upgrade() { ARG_CONTRACT_PACKAGE => stored_package_hash }, ) - .with_protocol_version(new_protocol_version) .build(); builder.exec(upgrade_request).expect_success().commit(); @@ -1007,7 +995,7 @@ enum InvocationType { } fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { - let (mut builder, new_protocol_version, _) = setup_upgrade_threshold_state(); + let (mut builder, _) = setup_upgrade_threshold_state(); let runtime_args = runtime_args! { PURSE_NAME_ARG_NAME => PURSE_1 @@ -1041,7 +1029,6 @@ fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { ENTRY_POINT_ADD, runtime_args, ) - .with_protocol_version(new_protocol_version) .build() } InvocationType::ByPackageHash(maybe_contract_version) => { @@ -1052,7 +1039,6 @@ fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { ENTRY_POINT_ADD, runtime_args, ) - .with_protocol_version(new_protocol_version) .build() } InvocationType::ByContractHash => ExecuteRequestBuilder::contract_call_by_hash( @@ -1061,7 +1047,6 @@ fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { ENTRY_POINT_ADD, runtime_args, ) - .with_protocol_version(new_protocol_version) .build(), InvocationType::ByContractName => ExecuteRequestBuilder::contract_call_by_name( *DEFAULT_ACCOUNT_ADDR, @@ -1069,7 +1054,6 @@ fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { ENTRY_POINT_ADD, runtime_args, ) - .with_protocol_version(new_protocol_version) .build(), InvocationType::ByUpgrader => ExecuteRequestBuilder::standard( *DEFAULT_ACCOUNT_ADDR, @@ -1078,7 +1062,6 @@ fn call_and_migrate_purse_holder_contract(invocation_type: InvocationType) { ARG_CONTRACT_PACKAGE => package_hash }, ) - .with_protocol_version(new_protocol_version) .build(), }; diff --git a/execution_engine_testing/tests/src/test/wasmless_transfer.rs b/execution_engine_testing/tests/src/test/wasmless_transfer.rs index 89a9117545..9e8469bd4f 100644 --- a/execution_engine_testing/tests/src/test/wasmless_transfer.rs +++ b/execution_engine_testing/tests/src/test/wasmless_transfer.rs @@ -1,9 +1,8 @@ use once_cell::sync::Lazy; use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, UpgradeRequestBuilder, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, - PRODUCTION_RUN_GENESIS_REQUEST, + ExecuteRequestBuilder, LmdbWasmTestBuilder, TransferRequestBuilder, UpgradeRequestBuilder, + DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, DEFAULT_PROTOCOL_VERSION, LOCAL_GENESIS_REQUEST, }; use casper_execution_engine::engine_state::{ Error as CoreError, WASMLESS_TRANSFER_FIXED_GAS_PRICE, @@ -25,15 +24,17 @@ const TEST_PURSE_NAME: &str = "test_purse"; const ARG_PURSE_NAME: &str = "purse_name"; const ARG_UREF_NAME: &str = "uref_name"; -static ACCOUNT_1_SK: Lazy = +static ACCOUNT_1_SECRET_KEY: Lazy = Lazy::new(|| SecretKey::secp256k1_from_bytes([234u8; 32]).unwrap()); -static ACCOUNT_1_PK: Lazy = Lazy::new(|| PublicKey::from(&*ACCOUNT_1_SK)); -static ACCOUNT_1_ADDR: Lazy = Lazy::new(|| ACCOUNT_1_PK.to_account_hash()); +static ACCOUNT_1_PUBLIC_KEY: Lazy = + Lazy::new(|| PublicKey::from(&*ACCOUNT_1_SECRET_KEY)); +static ACCOUNT_1_ADDR: Lazy = Lazy::new(|| ACCOUNT_1_PUBLIC_KEY.to_account_hash()); -static ACCOUNT_2_SK: Lazy = +static ACCOUNT_2_SECRET_KEY: Lazy = Lazy::new(|| SecretKey::secp256k1_from_bytes([210u8; 32]).unwrap()); -static ACCOUNT_2_PK: Lazy = Lazy::new(|| PublicKey::from(&*ACCOUNT_2_SK)); -static ACCOUNT_2_ADDR: Lazy = Lazy::new(|| ACCOUNT_2_PK.to_account_hash()); +static ACCOUNT_2_PUBLIC_KEY: Lazy = + Lazy::new(|| PublicKey::from(&*ACCOUNT_2_SECRET_KEY)); +static ACCOUNT_2_ADDR: Lazy = Lazy::new(|| ACCOUNT_2_PUBLIC_KEY.to_account_hash()); #[ignore] #[test] @@ -123,7 +124,7 @@ fn transfer_wasmless(wasmless_transfer: WasmlessTransfer) { } WasmlessTransfer::AccountMainPurseToPublicKeyMainPurse => { runtime_args! { - mint::ARG_TARGET => ACCOUNT_2_PK.clone(), + mint::ARG_TARGET => ACCOUNT_2_PUBLIC_KEY.clone(), mint::ARG_AMOUNT => transfer_amount, mint::ARG_ID => id } @@ -146,7 +147,7 @@ fn transfer_wasmless(wasmless_transfer: WasmlessTransfer) { WasmlessTransfer::PurseToPublicKey => { runtime_args! { mint::ARG_SOURCE => account_1_purse, - mint::ARG_TARGET => ACCOUNT_2_PK.clone(), + mint::ARG_TARGET => ACCOUNT_2_PUBLIC_KEY.clone(), mint::ARG_AMOUNT => transfer_amount, mint::ARG_ID => id } @@ -161,21 +162,14 @@ fn transfer_wasmless(wasmless_transfer: WasmlessTransfer) { } }; - let no_wasm_transfer_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let no_wasm_transfer_request = TransferRequestBuilder::new(0, AccountHash::default()) + .with_args(runtime_args) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); builder - .exec(no_wasm_transfer_request) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request) + .expect_success(); let wasmless_transfer_gas_cost = Gas::from(MintCosts::default().transfer); let wasmless_transfer_cost = Motes::from_gas( @@ -497,16 +491,10 @@ fn invalid_transfer_wasmless(invalid_wasmless_transfer: InvalidWasmlessTransfer) } }; - let no_wasm_transfer_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(addr) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[addr]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let no_wasm_transfer_request = TransferRequestBuilder::new(0, AccountHash::default()) + .with_args(runtime_args) + .with_initiator(addr) + .build(); let account_1_purse = builder .get_entity_by_account_hash(*ACCOUNT_1_ADDR) @@ -515,18 +503,13 @@ fn invalid_transfer_wasmless(invalid_wasmless_transfer: InvalidWasmlessTransfer) let account_1_starting_balance = builder.get_purse_balance(account_1_purse); - builder.exec(no_wasm_transfer_request); + builder.transfer_and_commit(no_wasm_transfer_request); let result = builder .get_last_exec_result() - .expect("Expected to be called after run()") - .get(0) - .cloned() - .expect("Unable to get first deploy result"); - - assert!(result.is_failure(), "was expected to fail"); + .expect("Expected to be called after run()"); - let error = result.as_error().expect("should have error"); + let error = result.error().expect("should have error"); let account_1_closing_balance = builder.get_purse_balance(account_1_purse); @@ -582,27 +565,13 @@ fn transfer_wasmless_should_create_target_if_it_doesnt_exist() { let account_1_starting_balance = builder.get_purse_balance(account_1_purse); - let runtime_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => >::None - }; - - let native_transfer_request = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; + let no_wasm_transfer_request = TransferRequestBuilder::new(transfer_amount, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) + .build(); builder - .exec(native_transfer_request) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request) + .expect_success(); let account_2 = builder .get_entity_by_account_hash(*ACCOUNT_2_ADDR) @@ -651,7 +620,7 @@ fn init_wasmless_transform_builder(create_account_2: bool) -> LmdbWasmTestBuilde .build(); builder - .run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()) + .run_genesis(LOCAL_GENESIS_REQUEST.clone()) .exec(create_account_1_request) .expect_success() .commit(); @@ -721,27 +690,14 @@ fn transfer_wasmless_should_fail_without_main_purse_minimum_balance() { let account_1_starting_balance = builder.get_purse_balance(account_1_purse); - let runtime_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => account_1_to_account_2_amount, - mint::ARG_ID => >::None - }; - - let no_wasm_transfer_request_1 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(account_1_to_account_2_amount, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; builder - .exec(no_wasm_transfer_request_1) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request_1) + .expect_success(); let account_2 = builder .get_entity_by_account_hash(*ACCOUNT_2_ADDR) @@ -760,24 +716,12 @@ fn transfer_wasmless_should_fail_without_main_purse_minimum_balance() { ); // Another transfer but this time created account tries to do a transfer - let runtime_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => account_2_to_account_1_amount, - mint::ARG_ID => >::None - }; - - let no_wasm_transfer_request_2 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_2_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_2_ADDR]) - .with_deploy_hash([43; 32]) + let no_wasm_transfer_request_2 = + TransferRequestBuilder::new(account_2_to_account_1_amount, *ACCOUNT_1_ADDR) + .with_initiator(*ACCOUNT_2_ADDR) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - builder.exec(no_wasm_transfer_request_2).commit(); + builder.transfer_and_commit(no_wasm_transfer_request_2); // TODO: reenable when new payment code is added // let exec_result = &builder.get_last_exec_result().unwrap()[0]; // let error = exec_result @@ -820,27 +764,14 @@ fn transfer_wasmless_should_transfer_funds_after_paying_for_transfer() { let account_1_starting_balance = builder.get_purse_balance(account_1_purse); - let runtime_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => account_1_to_account_2_amount, - mint::ARG_ID => >::None - }; - - let no_wasm_transfer_request_1 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(account_1_to_account_2_amount, *ACCOUNT_2_ADDR) + .with_initiator(*ACCOUNT_1_ADDR) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; builder - .exec(no_wasm_transfer_request_1) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request_1) + .expect_success(); let account_2 = builder .get_entity_by_account_hash(*ACCOUNT_2_ADDR) @@ -859,26 +790,13 @@ fn transfer_wasmless_should_transfer_funds_after_paying_for_transfer() { ); // Another transfer but this time created account tries to do a transfer - let runtime_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_1_ADDR, - mint::ARG_AMOUNT => account_2_to_account_1_amount, - mint::ARG_ID => >::None - }; - - let no_wasm_transfer_request_2 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_2_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_2_ADDR]) - .with_deploy_hash([43; 32]) + let no_wasm_transfer_request_2 = + TransferRequestBuilder::new(account_2_to_account_1_amount, *ACCOUNT_1_ADDR) + .with_initiator(*ACCOUNT_2_ADDR) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; builder - .exec(no_wasm_transfer_request_2) - .commit() + .transfer_and_commit(no_wasm_transfer_request_2) .expect_success(); } @@ -913,25 +831,13 @@ fn transfer_wasmless_should_fail_with_secondary_purse_insufficient_funds() { let account_1_starting_balance = builder.get_purse_balance(account_1_purse); assert_eq!(account_1_starting_balance, U512::zero()); - let runtime_args = runtime_args! { - mint::ARG_SOURCE => account_1_purse, - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => account_1_to_account_2_amount, - mint::ARG_ID => >::None - }; - - let no_wasm_transfer_request_1 = { - let deploy_item = DeployItemBuilder::new() - .with_address(*ACCOUNT_1_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(runtime_args) - .with_authorization_keys(&[*ACCOUNT_1_ADDR]) - .with_deploy_hash([42; 32]) + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(account_1_to_account_2_amount, *ACCOUNT_2_ADDR) + .with_source(account_1_purse) + .with_initiator(*ACCOUNT_1_ADDR) .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item).build() - }; - builder.exec(no_wasm_transfer_request_1).commit(); + builder.transfer_and_commit(no_wasm_transfer_request_1); //TODO: reenable when new payment code is added // let exec_result = &builder.get_last_exec_result().unwrap()[0]; // let error = exec_result.as_error().expect("should have error"); @@ -959,7 +865,7 @@ fn transfer_wasmless_should_observe_upgraded_cost() { const DEFAULT_ACTIVATION_POINT: EraId = EraId::new(1); - let old_protocol_version = *DEFAULT_PROTOCOL_VERSION; + let old_protocol_version = DEFAULT_PROTOCOL_VERSION; let new_protocol_version = ProtocolVersion::from_parts( old_protocol_version.value().major, old_protocol_version.value().minor, @@ -967,7 +873,7 @@ fn transfer_wasmless_should_observe_upgraded_cost() { ); let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(PRODUCTION_RUN_GENESIS_REQUEST.clone()); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); let default_account = builder .get_entity_by_account_hash(*DEFAULT_ACCOUNT_ADDR) @@ -975,7 +881,7 @@ fn transfer_wasmless_should_observe_upgraded_cost() { let mut upgrade_request = { UpgradeRequestBuilder::new() - .with_current_protocol_version(*DEFAULT_PROTOCOL_VERSION) + .with_current_protocol_version(DEFAULT_PROTOCOL_VERSION) .with_new_protocol_version(new_protocol_version) .with_activation_point(DEFAULT_ACTIVATION_POINT) .build() @@ -985,29 +891,12 @@ fn transfer_wasmless_should_observe_upgraded_cost() { let default_account_balance_before = builder.get_purse_balance(default_account.main_purse()); - let no_wasm_transfer_request_1 = { - let wasmless_transfer_args = runtime_args! { - mint::ARG_TARGET => *ACCOUNT_2_ADDR, - mint::ARG_AMOUNT => transfer_amount, - mint::ARG_ID => >::None - }; - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_empty_payment_bytes(runtime_args! {}) - .with_transfer_args(wasmless_transfer_args) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - ExecuteRequestBuilder::from_deploy_item(deploy_item) - .with_protocol_version(new_protocol_version) - .build() - }; + let no_wasm_transfer_request_1 = + TransferRequestBuilder::new(transfer_amount, *ACCOUNT_2_ADDR).build(); builder - .exec(no_wasm_transfer_request_1) - .expect_success() - .commit(); + .transfer_and_commit(no_wasm_transfer_request_1) + .expect_success(); let default_account_balance_after = builder.get_purse_balance(default_account.main_purse()); diff --git a/node/Cargo.toml b/node/Cargo.toml index f27404562f..b707a61fc4 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -23,6 +23,7 @@ base16 = "0.2.1" base64 = "0.13.0" bincode = "1" bytes = "1.0.1" +casper-binary-port = { version = "1.0.0", path = "../binary_port" } casper-execution-engine = { version = "6.0.0", path = "../execution_engine" } casper-json-rpc = { version = "1.1.0", path = "../json_rpc" } casper-storage = { version = "1.4.3", path = "../storage" } @@ -84,7 +85,7 @@ tokio-serde = { version = "0.8.0", features = ["bincode"] } tokio-stream = { version = "0.1.4", features = ["sync"] } tokio-util = { version = "0.6.4", features = ["codec"] } mio = "0.8.11" -toml = "0.5.6" +toml = { version = "0.7.8", features = ["preserve_order"] } tower = { version = "0.4.6", features = ["limit"] } tracing = "0.1.18" tracing-futures = "0.2.5" diff --git a/node/src/components/binary_port.rs b/node/src/components/binary_port.rs index 59fabd9f35..8ae69e6c3f 100644 --- a/node/src/components/binary_port.rs +++ b/node/src/components/binary_port.rs @@ -9,6 +9,12 @@ mod tests; use std::{convert::TryFrom, net::SocketAddr, sync::Arc}; use bytes::Bytes; +use casper_binary_port::{ + BinaryRequest, BinaryRequestHeader, BinaryRequestTag, BinaryResponse, BinaryResponseAndRequest, + DictionaryItemIdentifier, DictionaryQueryResult, ErrorCode, GetRequest, GetTrieFullResult, + GlobalStateQueryResult, GlobalStateRequest, InformationRequest, InformationRequestTag, + NodeStatus, PayloadType, ReactorStateName, RecordId, TransactionWithExecutionInfo, +}; use casper_storage::{ data_access_layer::{ tagged_values::{TaggedValuesRequest, TaggedValuesResult, TaggedValuesSelection}, @@ -18,17 +24,11 @@ use casper_storage::{ }; use casper_types::{ addressable_entity::NamedKeyAddr, - binary_port::{ - self, BinaryRequest, BinaryRequestHeader, BinaryRequestTag, BinaryResponse, - BinaryResponseAndRequest, DbRawBytesSpec, DictionaryItemIdentifier, DictionaryQueryResult, - GetRequest, GetTrieFullResult, GlobalStateQueryResult, GlobalStateRequest, - InformationRequest, InformationRequestTag, NodeStatus, ReactorStateName, RecordId, - TransactionWithExecutionInfo, - }, bytesrepr::{self, FromBytes, ToBytes}, - BlockHeader, BlockIdentifier, Digest, EntityAddr, GlobalStateIdentifier, Key, Peers, - ProtocolVersion, SignedBlock, StoredValue, TimeDiff, Timestamp, Transaction, + BlockIdentifier, Digest, EntityAddr, GlobalStateIdentifier, Key, Peers, ProtocolVersion, + SignedBlock, StoredValue, TimeDiff, Transaction, }; + use datasize::DataSize; use futures::{future::BoxFuture, FutureExt}; use juliet::{ @@ -48,7 +48,7 @@ use tokio::{ use tracing::{debug, error, info, warn}; use crate::{ - contract_runtime::SpeculativeExecutionState, + contract_runtime::SpeculativeExecutionResult, effect::{ requests::{ AcceptTransactionRequest, BlockSynchronizerRequest, ChainspecRawBytesRequest, @@ -65,6 +65,7 @@ use crate::{ use self::{error::Error, metrics::Metrics}; use super::{Component, ComponentState, InitializedComponent, PortBoundComponent}; + pub(crate) use config::Config; pub(crate) use event::Event; @@ -108,135 +109,6 @@ impl BinaryPort { } } -impl Component for BinaryPort -where - REv: From - + From - + From - + From - + From - + From - + From - + From - + From - + From - + Send, -{ - type Event = Event; - - fn handle_event( - &mut self, - effect_builder: EffectBuilder, - _rng: &mut NodeRng, - event: Self::Event, - ) -> Effects { - match &self.state { - ComponentState::Uninitialized => { - warn!( - ?event, - name = >::name(self), - "should not handle this event when component is uninitialized" - ); - Effects::new() - } - ComponentState::Initializing => match event { - Event::Initialize => { - let (effects, state) = self.bind(self.config.enable_server, effect_builder); - >::set_state(self, state); - effects - } - _ => { - warn!( - ?event, - name = >::name(self), - "binary port is initializing, ignoring event" - ); - Effects::new() - } - }, - ComponentState::Initialized => match event { - Event::Initialize => { - error!( - ?event, - name = >::name(self), - "component already initialized" - ); - Effects::new() - } - Event::AcceptConnection { - stream, - peer, - responder, - } => { - if let Ok(permit) = Arc::clone(&self.connection_limit).try_acquire_owned() { - self.metrics.binary_port_connections_count.inc(); - let config = Arc::clone(&self.config); - tokio::spawn(handle_client(peer, stream, effect_builder, config, permit)); - } else { - warn!( - "connection limit reached, dropping connection from {}", - peer - ); - } - responder.respond(()).ignore() - } - Event::HandleRequest { request, responder } => { - let config = Arc::clone(&self.config); - let metrics = Arc::clone(&self.metrics); - async move { - let response = - handle_request(request, effect_builder, &config, &metrics).await; - responder.respond(response).await - } - .ignore() - } - }, - ComponentState::Fatal(msg) => { - error!( - msg, - ?event, - name = >::name(self), - "should not handle this event when this component has fatal error" - ); - Effects::new() - } - } - } - - fn name(&self) -> &str { - COMPONENT_NAME - } -} - -impl InitializedComponent for BinaryPort -where - REv: From - + From - + From - + From - + From - + From - + From - + From - + From - + From - + Send, -{ - fn state(&self) -> &ComponentState { - &self.state - } - - fn set_state(&mut self, new_state: ComponentState) { - info!( - ?new_state, - name = >::name(self), - "component state changed" - ); - - self.state = new_state; - } -} - async fn handle_request( req: BinaryRequest, effect_builder: EffectBuilder, @@ -256,47 +128,27 @@ where + From + Send, { - let version = effect_builder.get_protocol_version().await; + let protocol_version = effect_builder.get_protocol_version().await; match req { BinaryRequest::TryAcceptTransaction { transaction } => { metrics.binary_port_try_accept_transaction_count.inc(); - try_accept_transaction(effect_builder, transaction, None, version).await + try_accept_transaction(effect_builder, transaction, false, protocol_version).await } - BinaryRequest::TrySpeculativeExec { - transaction, - state_root_hash, - block_time, - protocol_version, - speculative_exec_at_block, - } => { + BinaryRequest::TrySpeculativeExec { transaction } => { metrics.binary_port_try_speculative_exec_count.inc(); if !config.allow_request_speculative_exec { - return BinaryResponse::new_error( - binary_port::ErrorCode::FunctionDisabled, - protocol_version, - ); + return BinaryResponse::new_error(ErrorCode::FunctionDisabled, protocol_version); } - let response = try_accept_transaction( - effect_builder, - transaction.clone(), - Some(speculative_exec_at_block), - version, - ) - .await; + let response = + try_accept_transaction(effect_builder, transaction.clone(), true, protocol_version) + .await; if !response.is_success() { return response; } - try_speculative_execution( - effect_builder, - state_root_hash, - block_time, - protocol_version, - transaction, - ) - .await + try_speculative_execution(effect_builder, transaction, protocol_version).await } BinaryRequest::Get(get_req) => { - handle_get_request(get_req, effect_builder, config, metrics, version).await + handle_get_request(get_req, effect_builder, config, metrics, protocol_version).await } } } @@ -328,7 +180,7 @@ where } if RecordId::try_from(record_type_tag) == Ok(RecordId::Transfer) => { metrics.binary_port_get_record_count.inc(); let Ok(block_hash) = bytesrepr::deserialize_from_slice(&key) else { - return BinaryResponse::new_error(binary_port::ErrorCode::BadRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::BadRequest, protocol_version); }; let Some(transfers) = effect_builder .get_block_transfers_from_storage(block_hash) @@ -336,10 +188,9 @@ where return BinaryResponse::new_empty(protocol_version); }; let Ok(serialized) = bincode::serialize(&transfers) else { - return BinaryResponse::new_error(binary_port::ErrorCode::InternalError, protocol_version); + return BinaryResponse::new_error(ErrorCode::InternalError, protocol_version); }; - let bytes = DbRawBytesSpec::new_current(&serialized); - BinaryResponse::from_db_raw_bytes(RecordId::Transfer, Some(bytes), protocol_version) + BinaryResponse::from_raw_bytes(PayloadType::Transfers, serialized, protocol_version) } GetRequest::Record { record_type_tag, @@ -348,22 +199,28 @@ where metrics.binary_port_get_record_count.inc(); match RecordId::try_from(record_type_tag) { Ok(record_id) => { - let maybe_raw_bytes = effect_builder.get_raw_data(record_id, key).await; - BinaryResponse::from_db_raw_bytes(record_id, maybe_raw_bytes, protocol_version) + let Some(db_bytes) = effect_builder.get_raw_data(record_id, key).await else { + return BinaryResponse::new_empty(protocol_version); + }; + let payload_type = PayloadType::from_record_id(record_id, db_bytes.is_legacy()); + BinaryResponse::from_raw_bytes( + payload_type, + db_bytes.into_raw_bytes(), + protocol_version, + ) + } + Err(_) => { + BinaryResponse::new_error(ErrorCode::UnsupportedRequest, protocol_version) } - Err(_) => BinaryResponse::new_error( - binary_port::ErrorCode::UnsupportedRequest, - protocol_version, - ), } } GetRequest::Information { info_type_tag, key } => { metrics.binary_port_get_info_count.inc(); let Ok(tag) = InformationRequestTag::try_from(info_type_tag) else { - return BinaryResponse::new_error(binary_port::ErrorCode::UnsupportedRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::UnsupportedRequest, protocol_version); }; let Ok(req) = InformationRequest::try_from((tag, &key[..])) else { - return BinaryResponse::new_error(binary_port::ErrorCode::BadRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::BadRequest, protocol_version); }; handle_info_request(req, effect_builder, protocol_version).await } @@ -373,7 +230,6 @@ where } } } - async fn handle_get_all_items( state_identifier: Option, key_tag: casper_types::KeyTag, @@ -392,11 +248,11 @@ where BinaryResponse::from_value(values, protocol_version) } TaggedValuesResult::RootNotFound => { - let error_code = binary_port::ErrorCode::RootNotFound; + let error_code = ErrorCode::RootNotFound; BinaryResponse::new_error(error_code, protocol_version) } TaggedValuesResult::Failure(_err) => { - BinaryResponse::new_error(binary_port::ErrorCode::InternalError, protocol_version) + BinaryResponse::new_error(ErrorCode::InternalError, protocol_version) } } } @@ -430,10 +286,7 @@ where key_tag, } => { if !config.allow_request_get_all_values { - BinaryResponse::new_error( - binary_port::ErrorCode::FunctionDisabled, - protocol_version, - ) + BinaryResponse::new_error(ErrorCode::FunctionDisabled, protocol_version) } else { handle_get_all_items(state_identifier, key_tag, effect_builder, protocol_version) .await @@ -441,10 +294,7 @@ where } GlobalStateRequest::Trie { trie_key } => { let response = if !config.allow_request_get_trie { - BinaryResponse::new_error( - binary_port::ErrorCode::FunctionDisabled, - protocol_version, - ) + BinaryResponse::new_error(ErrorCode::FunctionDisabled, protocol_version) } else { let req = TrieRequest::new(trie_key, None); match effect_builder.get_trie(req).await.into_legacy() { @@ -452,10 +302,9 @@ where GetTrieFullResult::new(result.map(TrieRaw::into_inner)), protocol_version, ), - Err(_err) => BinaryResponse::new_error( - binary_port::ErrorCode::InternalError, - protocol_version, - ), + Err(_err) => { + BinaryResponse::new_error(ErrorCode::InternalError, protocol_version) + } } }; response @@ -541,7 +390,7 @@ async fn get_dictionary_item_by_legacy_named_key( entity_key: Key, dictionary_name: String, dictionary_item_key: String, -) -> Result, binary_port::ErrorCode> +) -> Result, ErrorCode> where REv: From + From + From, { @@ -553,10 +402,10 @@ where let named_keys = match &*value { StoredValue::Account(account) => account.named_keys(), StoredValue::Contract(contract) => contract.named_keys(), - _ => return Err(binary_port::ErrorCode::DictionaryURefNotFound), + _ => return Err(ErrorCode::DictionaryURefNotFound), }; let Some(uref) = named_keys.get(&dictionary_name).and_then(Key::as_uref) else { - return Err(binary_port::ErrorCode::DictionaryURefNotFound); + return Err(ErrorCode::DictionaryURefNotFound); }; let key = Key::dictionary(*uref, dictionary_item_key.as_bytes()); let Some(query_result) = @@ -568,9 +417,9 @@ where Ok(Some(DictionaryQueryResult::new(key, query_result))) } QueryResult::RootNotFound | QueryResult::ValueNotFound(_) => { - Err(binary_port::ErrorCode::DictionaryURefNotFound) + Err(ErrorCode::DictionaryURefNotFound) } - QueryResult::Failure(_) => Err(binary_port::ErrorCode::QueryFailedToExecute), + QueryResult::Failure(_) => Err(ErrorCode::FailedQuery), } } @@ -580,21 +429,21 @@ async fn get_dictionary_item_by_named_key( entity_addr: EntityAddr, dictionary_name: String, dictionary_item_key: String, -) -> Result, binary_port::ErrorCode> +) -> Result, ErrorCode> where REv: From + From + From, { let Ok(key_addr) = NamedKeyAddr::new_from_string(entity_addr, dictionary_name) else { - return Err(binary_port::ErrorCode::InternalError); + return Err(ErrorCode::InternalError); }; let req = QueryRequest::new(state_root_hash, Key::NamedKey(key_addr), vec![]); match effect_builder.query_global_state(req).await { QueryResult::Success { value, .. } => { let StoredValue::NamedKey(key_val) = &*value else { - return Err(binary_port::ErrorCode::DictionaryURefNotFound); + return Err(ErrorCode::DictionaryURefNotFound); }; let Ok(Key::URef(uref)) = key_val.get_key() else { - return Err(binary_port::ErrorCode::DictionaryURefNotFound); + return Err(ErrorCode::DictionaryURefNotFound); }; let key = Key::dictionary(uref, dictionary_item_key.as_bytes()); let Some(query_result) = @@ -605,9 +454,9 @@ where Ok(Some(DictionaryQueryResult::new(key, query_result))) } QueryResult::RootNotFound | QueryResult::ValueNotFound(_) => { - Err(binary_port::ErrorCode::DictionaryURefNotFound) + Err(ErrorCode::DictionaryURefNotFound) } - QueryResult::Failure(_) => Err(binary_port::ErrorCode::QueryFailedToExecute), + QueryResult::Failure(_) => Err(ErrorCode::FailedQuery), } } @@ -616,7 +465,7 @@ async fn get_global_state_item( state_root_hash: Digest, base_key: Key, path: Vec, -) -> Result, binary_port::ErrorCode> +) -> Result, ErrorCode> where REv: From + From + From, { @@ -627,9 +476,9 @@ where QueryResult::Success { value, proofs } => { Ok(Some(GlobalStateQueryResult::new(*value, proofs))) } - QueryResult::RootNotFound => Err(binary_port::ErrorCode::RootNotFound), - QueryResult::ValueNotFound(_) => Err(binary_port::ErrorCode::NotFound), - QueryResult::Failure(_) => Err(binary_port::ErrorCode::QueryFailedToExecute), + QueryResult::RootNotFound => Err(ErrorCode::RootNotFound), + QueryResult::ValueNotFound(_) => Err(ErrorCode::NotFound), + QueryResult::Failure(_) => Err(ErrorCode::FailedQuery), } } @@ -778,7 +627,7 @@ where let Ok(uptime) = TimeDiff::try_from(node_uptime) else { return BinaryResponse::new_error( - binary_port::ErrorCode::InternalError, + ErrorCode::InternalError, protocol_version, ) }; @@ -808,14 +657,14 @@ where async fn try_accept_transaction( effect_builder: EffectBuilder, transaction: Transaction, - speculative_exec_at: Option, + is_speculative: bool, protocol_version: ProtocolVersion, ) -> BinaryResponse where REv: From, { effect_builder - .try_accept_transaction(transaction, speculative_exec_at.map(Box::new)) + .try_accept_transaction(transaction, is_speculative) .await .map_or_else( |err| BinaryResponse::new_error(err.into(), protocol_version), @@ -825,28 +674,32 @@ where async fn try_speculative_execution( effect_builder: EffectBuilder, - state_root_hash: Digest, - block_time: Timestamp, - protocol_version: ProtocolVersion, transaction: Transaction, + protocol_version: ProtocolVersion, ) -> BinaryResponse where - REv: From + From, + REv: From + From + From, { - effect_builder - .speculatively_execute( - SpeculativeExecutionState { - state_root_hash, - block_time, - protocol_version, - }, - Box::new(transaction), - ) + let tip = match effect_builder + .get_highest_complete_block_header_from_storage() .await - .map_or_else( - |err| BinaryResponse::new_error(err.into(), protocol_version), - |val| BinaryResponse::from_value(val, protocol_version), - ) + { + Some(tip) => tip, + None => return BinaryResponse::new_error(ErrorCode::NoCompleteBlocks, protocol_version), + }; + + let result = effect_builder + .speculatively_execute(Box::new(tip), Box::new(transaction)) + .await; + + match result { + SpeculativeExecutionResult::InvalidTransaction(ite) => { + BinaryResponse::new_error(ite.into(), protocol_version) + } + SpeculativeExecutionResult::WasmV1(spec_exec_result) => { + BinaryResponse::from_value(spec_exec_result, protocol_version) + } + } } async fn client_loop( @@ -894,26 +747,23 @@ where REv: From, { let Ok((header, remainder)) = BinaryRequestHeader::from_bytes(payload) else { - return BinaryResponse::new_error(binary_port::ErrorCode::BadRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::BadRequest, protocol_version); }; if !header .protocol_version() .is_compatible_with(&protocol_version) { - return BinaryResponse::new_error( - binary_port::ErrorCode::UnsupportedProtocolVersion, - protocol_version, - ); + return BinaryResponse::new_error(ErrorCode::UnsupportedProtocolVersion, protocol_version); } // we might receive a request added in a minor version if we're behind let Ok(tag) = BinaryRequestTag::try_from(header.type_tag()) else { - return BinaryResponse::new_error(binary_port::ErrorCode::UnsupportedRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::UnsupportedRequest, protocol_version); }; let Ok(request) = BinaryRequest::try_from((tag, remainder)) else { - return BinaryResponse::new_error(binary_port::ErrorCode::BadRequest, protocol_version); + return BinaryResponse::new_error(ErrorCode::BadRequest, protocol_version); }; effect_builder @@ -1016,42 +866,6 @@ async fn run_server( } } -impl PortBoundComponent for BinaryPort -where - REv: From - + From - + From - + From - + From - + From - + From - + From - + From - + From - + Send, -{ - type Error = ListeningError; - type ComponentEvent = Event; - - fn listen( - &mut self, - effect_builder: EffectBuilder, - ) -> Result, Self::Error> { - let local_addr = Arc::clone(&self.local_addr); - let server_join_handle = tokio::spawn(run_server( - local_addr, - effect_builder, - Arc::clone(&self.config), - Arc::clone(&self.shutdown_trigger), - )); - self.server_join_handle - .set(server_join_handle) - .expect("server join handle should not be set elsewhere"); - - Ok(Effects::new()) - } -} - impl Finalize for BinaryPort { fn finalize(mut self) -> BoxFuture<'static, ()> { self.shutdown_trigger.notify_one(); @@ -1119,3 +933,168 @@ where .map(|header| *header.state_root_hash()), } } + +impl Component for BinaryPort +where + REv: From + + From + + From + + From + + From + + From + + From + + From + + From + + From + + Send, +{ + type Event = Event; + + fn name(&self) -> &str { + COMPONENT_NAME + } + + fn handle_event( + &mut self, + effect_builder: EffectBuilder, + _rng: &mut NodeRng, + event: Self::Event, + ) -> Effects { + match &self.state { + ComponentState::Uninitialized => { + warn!( + ?event, + name = >::name(self), + "should not handle this event when component is uninitialized" + ); + Effects::new() + } + ComponentState::Initializing => match event { + Event::Initialize => { + let (effects, state) = self.bind(self.config.enable_server, effect_builder); + >::set_state(self, state); + effects + } + _ => { + warn!( + ?event, + name = >::name(self), + "binary port is initializing, ignoring event" + ); + Effects::new() + } + }, + ComponentState::Initialized => match event { + Event::Initialize => { + error!( + ?event, + name = >::name(self), + "component already initialized" + ); + Effects::new() + } + Event::AcceptConnection { + stream, + peer, + responder, + } => { + if let Ok(permit) = Arc::clone(&self.connection_limit).try_acquire_owned() { + self.metrics.binary_port_connections_count.inc(); + let config = Arc::clone(&self.config); + tokio::spawn(handle_client(peer, stream, effect_builder, config, permit)); + } else { + warn!( + "connection limit reached, dropping connection from {}", + peer + ); + } + responder.respond(()).ignore() + } + Event::HandleRequest { request, responder } => { + let config = Arc::clone(&self.config); + let metrics = Arc::clone(&self.metrics); + async move { + let response = + handle_request(request, effect_builder, &config, &metrics).await; + responder.respond(response).await + } + .ignore() + } + }, + ComponentState::Fatal(msg) => { + error!( + msg, + ?event, + name = >::name(self), + "should not handle this event when this component has fatal error" + ); + Effects::new() + } + } + } +} + +impl InitializedComponent for BinaryPort +where + REv: From + + From + + From + + From + + From + + From + + From + + From + + From + + From + + Send, +{ + fn state(&self) -> &ComponentState { + &self.state + } + + fn set_state(&mut self, new_state: ComponentState) { + info!( + ?new_state, + name = >::name(self), + "component state changed" + ); + + self.state = new_state; + } +} + +impl PortBoundComponent for BinaryPort +where + REv: From + + From + + From + + From + + From + + From + + From + + From + + From + + From + + Send, +{ + type Error = ListeningError; + type ComponentEvent = Event; + + fn listen( + &mut self, + effect_builder: EffectBuilder, + ) -> Result, Self::Error> { + let local_addr = Arc::clone(&self.local_addr); + let server_join_handle = tokio::spawn(run_server( + local_addr, + effect_builder, + Arc::clone(&self.config), + Arc::clone(&self.shutdown_trigger), + )); + self.server_join_handle + .set(server_join_handle) + .expect("server join handle should not be set elsewhere"); + + Ok(Effects::new()) + } +} diff --git a/node/src/components/binary_port/event.rs b/node/src/components/binary_port/event.rs index b6de07242f..200e7badf7 100644 --- a/node/src/components/binary_port/event.rs +++ b/node/src/components/binary_port/event.rs @@ -3,7 +3,7 @@ use std::{ net::SocketAddr, }; -use casper_types::binary_port::{BinaryRequest, BinaryResponse, GetRequest, GlobalStateRequest}; +use casper_binary_port::{BinaryRequest, BinaryResponse, GetRequest, GlobalStateRequest}; use tokio::net::TcpStream; use crate::effect::Responder; diff --git a/node/src/components/binary_port/tests.rs b/node/src/components/binary_port/tests.rs index 1302b191f2..3c82cf34a7 100644 --- a/node/src/components/binary_port/tests.rs +++ b/node/src/components/binary_port/tests.rs @@ -4,9 +4,10 @@ use derive_more::From; use rand::Rng; use serde::Serialize; +use casper_binary_port::{BinaryRequest, BinaryResponse, GetRequest, GlobalStateRequest}; + use casper_types::{ - binary_port::{BinaryRequest, BinaryResponse, GetRequest, GlobalStateRequest}, - BlockHeader, Digest, GlobalStateIdentifier, KeyTag, TestBlockBuilder, Timestamp, Transaction, + BlockHeader, Digest, GlobalStateIdentifier, KeyTag, Timestamp, Transaction, TransactionV1Builder, }; @@ -28,9 +29,8 @@ use futures::channel::oneshot::{self, Receiver}; use prometheus::Registry; use thiserror::Error as ThisError; -use casper_types::{ - binary_port::ErrorCode, testing::TestRng, Chainspec, ChainspecRawBytes, ProtocolVersion, -}; +use casper_binary_port::ErrorCode; +use casper_types::{testing::TestRng, Chainspec, ChainspecRawBytes, ProtocolVersion}; use crate::{ components::{ @@ -57,7 +57,7 @@ struct TestCase { } #[tokio::test] -async fn should_execute_enabled_functions() { +async fn should_enqueue_requests_for_enabled_functions() { let mut rng = TestRng::new(); let get_all_values_enabled = TestCase { @@ -261,6 +261,26 @@ impl Reactor for MockReactor { Effects::new() } Event::AcceptTransactionRequest(req) => req.responder.respond(Ok(())).ignore(), + Event::StorageRequest(StorageRequest::GetHighestCompleteBlockHeader { responder }) => { + let block_header_v2 = casper_types::BlockHeaderV2::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Timestamp::now(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + responder + .respond(Some(BlockHeader::V2(block_header_v2))) + .ignore() + } + Event::StorageRequest(req) => panic!("unexpected storage req {}", req), } } } @@ -286,6 +306,7 @@ enum Event { ReactorInfoRequest(ReactorInfoRequest), #[from] AcceptTransactionRequest(AcceptTransactionRequest), + StorageRequest(StorageRequest), } impl From for Event { @@ -319,8 +340,8 @@ impl From for Event { } impl From for Event { - fn from(_request: StorageRequest) -> Self { - unreachable!() + fn from(request: StorageRequest) -> Self { + Event::StorageRequest(request) } } @@ -338,6 +359,9 @@ impl Display for Event { Event::AcceptTransactionRequest(request) => { write!(formatter, "accept transaction request: {:?}", request) } + Event::StorageRequest(request) => { + write!(formatter, "storage request: {:?}", request) + } } } } @@ -373,12 +397,6 @@ fn trie_request() -> BinaryRequest { fn try_speculative_exec_request(rng: &mut TestRng) -> BinaryRequest { BinaryRequest::TrySpeculativeExec { transaction: Transaction::V1(TransactionV1Builder::new_random(rng).build().unwrap()), - state_root_hash: Digest::hash([1u8; 32]), - block_time: Timestamp::random(rng), - protocol_version: ProtocolVersion::from_parts(2, 0, 0), - speculative_exec_at_block: BlockHeader::V2( - TestBlockBuilder::new().build(rng).take_header(), - ), } } diff --git a/node/src/components/block_accumulator/tests.rs b/node/src/components/block_accumulator/tests.rs index c6608b3b38..fbcf7153c0 100644 --- a/node/src/components/block_accumulator/tests.rs +++ b/node/src/components/block_accumulator/tests.rs @@ -17,7 +17,7 @@ use tokio::time; use casper_types::{ generate_ed25519_keypair, testing::TestRng, ActivationPoint, BlockV2, ChainNameDigest, Chainspec, ChainspecRawBytes, FinalitySignature, FinalitySignatureV2, ProtocolVersion, - PublicKey, SecretKey, Signature, TestBlockBuilder, U512, + PublicKey, SecretKey, Signature, TestBlockBuilder, TransactionConfig, U512, }; use reactor::ReactorEvent; @@ -197,6 +197,7 @@ impl Reactor for MockReactor { chainspec.core_config.recent_era_count(), Some(registry), false, + TransactionConfig::default(), ) .unwrap(); diff --git a/node/src/components/block_synchronizer.rs b/node/src/components/block_synchronizer.rs index 8d1c6b3a68..cbf7a1d76b 100644 --- a/node/src/components/block_synchronizer.rs +++ b/node/src/components/block_synchronizer.rs @@ -1141,7 +1141,7 @@ impl BlockSynchronizer { } }; return effect_builder - .put_execution_results_to_storage( + .put_execution_artifacts_to_storage( block_hash, block_height, era_id, diff --git a/node/src/components/block_validator.rs b/node/src/components/block_validator.rs index 3ad7b88b53..a511132576 100644 --- a/node/src/components/block_validator.rs +++ b/node/src/components/block_validator.rs @@ -39,7 +39,7 @@ use crate::{ EffectBuilder, EffectExt, Effects, Responder, }, fatal, - types::{BlockWithMetadata, NodeId, TransactionExt, ValidatorMatrix}, + types::{BlockWithMetadata, NodeId, TransactionFootprint, ValidatorMatrix}, NodeRng, }; pub use config::Config; @@ -553,11 +553,12 @@ impl BlockValidator { .flat_map(|state| state.try_mark_invalid(&transaction_hash)); return respond(false, responders); } - let transaction_footprint = match item.footprint(&self.chainspec) { - Some(footprint) => footprint, - None => { + let transaction_footprint = match TransactionFootprint::new(&self.chainspec, &item) + { + Ok(footprint) => footprint, + Err(invalid_transaction_error) => { warn!( - %transaction_hash, + %transaction_hash, ?invalid_transaction_error, "could not convert transaction", ); // Hard failure - change state to Invalid. diff --git a/node/src/components/block_validator/state.rs b/node/src/components/block_validator/state.rs index d1bb5c8f40..a1ddc4b25f 100644 --- a/node/src/components/block_validator/state.rs +++ b/node/src/components/block_validator/state.rs @@ -550,7 +550,7 @@ mod tests { }; use super::{super::tests::*, *}; - use crate::{types::TransactionExt, utils::Loadable}; + use crate::utils::Loadable; struct Fixture<'a> { rng: &'a mut TestRng, @@ -574,8 +574,7 @@ mod tests { .map(|transaction| { ( transaction.hash(), - transaction - .footprint(&self.chainspec) + TransactionFootprint::new(&self.chainspec, transaction) .expect("must create footprint"), ) }) @@ -658,10 +657,10 @@ mod tests { } // Please note: values in the following test cases must much the production chainspec. - const MAX_STANDARD_COUNT: u64 = 100; - const MAX_AUCTION_COUNT: u64 = 200; + const MAX_STANDARD_COUNT: u64 = 50; + const MAX_AUCTION_COUNT: u64 = 100; const MAX_INSTALL_UPGRADE_COUNT: u64 = 2; - const MAX_MINT_COUNT: u64 = 1000; + const MAX_MINT_COUNT: u64 = 500; struct TestCase { mint_count: u64, @@ -1197,7 +1196,7 @@ mod tests { Transaction::V1(v1) => TransactionHash::V1(*v1.hash()), }; let chainspec = Chainspec::default(); - let footprint = transaction.footprint(&chainspec).unwrap(); + let footprint = TransactionFootprint::new(&chainspec, &transaction).unwrap(); // Ensure trying to add it doesn't change the state. let responders = state.try_add_transaction_footprint(&transaction_hash, &footprint); @@ -1257,7 +1256,7 @@ mod tests { // The invalid transaction should cause the state to go to `Invalid` and the responders to // be returned. let chainspec = Chainspec::default(); - let footprint = invalid_transaction.footprint(&chainspec).unwrap(); + let footprint = TransactionFootprint::new(&chainspec, &invalid_transaction).unwrap(); let responders = state.try_add_transaction_footprint(&transaction_hash, &footprint); assert_eq!(responders.len(), 1); assert!(matches!(state, BlockValidationState::Invalid(_))); diff --git a/node/src/components/consensus/era_supervisor.rs b/node/src/components/consensus/era_supervisor.rs index e126f53975..dd7854223e 100644 --- a/node/src/components/consensus/era_supervisor.rs +++ b/node/src/components/consensus/era_supervisor.rs @@ -30,8 +30,9 @@ use rand::Rng; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use tracing::{debug, error, info, trace, warn}; +use casper_binary_port::{ConsensusStatus, ConsensusValidatorChanges}; + use casper_types::{ - binary_port::{ConsensusStatus, ConsensusValidatorChanges}, Approval, AsymmetricType, BlockHash, BlockHeader, Chainspec, ConsensusProtocolName, Digest, DisplayIter, EraId, PublicKey, RewardedSignatures, Timestamp, Transaction, TransactionHash, ValidatorChange, diff --git a/node/src/components/consensus/tests/utils.rs b/node/src/components/consensus/tests/utils.rs index 9c29ab9815..615bdd24f8 100644 --- a/node/src/components/consensus/tests/utils.rs +++ b/node/src/components/consensus/tests/utils.rs @@ -57,7 +57,7 @@ where let accounts = stakes .into_iter() .map(|(pk, stake)| { - let motes = Motes::new(stake.into()); + let motes = Motes::new(stake); let validator_config = ValidatorConfig::new(motes, DelegationRate::zero()); AccountConfig::new(pk, motes, Some(validator_config)) }) diff --git a/node/src/components/contract_runtime.rs b/node/src/components/contract_runtime.rs index 136b3b784a..3e42e71215 100644 --- a/node/src/components/contract_runtime.rs +++ b/node/src/components/contract_runtime.rs @@ -26,8 +26,7 @@ use lmdb::DatabaseFlags; use prometheus::Registry; use tracing::{debug, error, info, trace}; -use casper_execution_engine::engine_state::{DeployItem, EngineConfigBuilder, ExecutionEngineV1}; - +use casper_execution_engine::engine_state::{EngineConfigBuilder, ExecutionEngineV1}; use casper_storage::{ data_access_layer::{ AddressableEntityRequest, BlockStore, DataAccessLayer, ExecutionResultsChecksumRequest, @@ -44,7 +43,6 @@ use casper_storage::{ }; use casper_types::{ ActivationPoint, Chainspec, ChainspecRawBytes, ChainspecRegistry, EraId, ProtocolUpgradeConfig, - Transaction, }; use crate::{ @@ -74,8 +72,8 @@ pub(crate) use operations::compute_execution_results_checksum; pub use operations::execute_finalized_block; use operations::speculatively_execute; pub(crate) use types::{ - BlockAndExecutionResults, ExecutionArtifact, ExecutionPreState, SpeculativeExecutionState, - StepEffectsAndUpcomingEraValidators, + BlockAndExecutionArtifacts, ExecutionArtifact, ExecutionPreState, SpeculativeExecutionResult, + StepOutcome, }; use utils::{exec_or_requeue, run_intensive_task}; @@ -143,6 +141,7 @@ impl ContractRuntime { .with_allow_unrestricted_transfers(chainspec.core_config.allow_unrestricted_transfers) .with_refund_handling(chainspec.core_config.refund_handling) .with_fee_handling(chainspec.core_config.fee_handling) + .with_protocol_version(chainspec.protocol_version()) .build(); let data_access_layer = Arc::new( @@ -572,30 +571,27 @@ impl ContractRuntime { effects } ContractRuntimeRequest::SpeculativelyExecute { - execution_prestate, + block_header, transaction, responder, } => { - if let Transaction::Deploy(deploy) = *transaction { - let execution_engine_v1 = Arc::clone(&self.execution_engine_v1); - let data_access_layer = Arc::clone(&self.data_access_layer); - async move { - let result = run_intensive_task(move || { - speculatively_execute( - data_access_layer.as_ref(), - execution_engine_v1.as_ref(), - execution_prestate, - DeployItem::from(deploy.clone()), - ) - }) - .await; - responder.respond(result).await - } - .ignore() - } else { - unreachable!() - //async move { responder.respond(Ok(None)).await }.ignore() + let chainspec = Arc::clone(&self.chainspec); + let data_access_layer = Arc::clone(&self.data_access_layer); + let execution_engine_v1 = Arc::clone(&self.execution_engine_v1); + async move { + let result = run_intensive_task(move || { + speculatively_execute( + data_access_layer.as_ref(), + chainspec.as_ref(), + execution_engine_v1.as_ref(), + *block_header, + *transaction, + ) + }) + .await; + responder.respond(result).await } + .ignore() } ContractRuntimeRequest::GetEraGasPrice { era_id, responder } => responder .respond(self.current_gas_price.maybe_gas_price_for_era_id(era_id)) diff --git a/node/src/components/contract_runtime/metrics.rs b/node/src/components/contract_runtime/metrics.rs index f93517442d..67fc2fe6a0 100644 --- a/node/src/components/contract_runtime/metrics.rs +++ b/node/src/components/contract_runtime/metrics.rs @@ -17,8 +17,8 @@ const EXPONENTIAL_BUCKET_COUNT: usize = 10; const RUN_EXECUTE_NAME: &str = "contract_runtime_run_execute"; const RUN_EXECUTE_HELP: &str = "time in seconds to execute but not commit a contract"; -const APPLY_EFFECT_NAME: &str = "contract_runtime_apply_commit"; -const APPLY_EFFECT_HELP: &str = "time in seconds to commit the execution effects of a contract"; +const COMMIT_EFFECT_NAME: &str = "contract_runtime_commit_effects"; +const COMMIT_EFFECT_HELP: &str = "time in seconds to commit the effects of a tranasction execution"; const COMMIT_GENESIS_NAME: &str = "contract_runtime_commit_genesis"; const COMMIT_GENESIS_HELP: &str = "time in seconds to commit an genesis"; @@ -76,7 +76,7 @@ const EXEC_QUEUE_SIZE_HELP: &str = #[derive(Debug)] pub struct Metrics { pub(super) run_execute: Histogram, - pub(super) apply_effect: Histogram, + pub(super) commit_effects: Histogram, pub(super) commit_genesis: Histogram, pub(super) commit_upgrade: Histogram, pub(super) run_query: Histogram, @@ -124,10 +124,10 @@ impl Metrics { RUN_EXECUTE_HELP, common_buckets.clone(), )?, - apply_effect: utils::register_histogram_metric( + commit_effects: utils::register_histogram_metric( registry, - APPLY_EFFECT_NAME, - APPLY_EFFECT_HELP, + COMMIT_EFFECT_NAME, + COMMIT_EFFECT_HELP, common_buckets.clone(), )?, run_query: utils::register_histogram_metric( @@ -224,7 +224,7 @@ impl Metrics { impl Drop for Metrics { fn drop(&mut self) { unregister_metric!(self.registry, self.run_execute); - unregister_metric!(self.registry, self.apply_effect); + unregister_metric!(self.registry, self.commit_effects); unregister_metric!(self.registry, self.commit_genesis); unregister_metric!(self.registry, self.commit_upgrade); unregister_metric!(self.registry, self.run_query); diff --git a/node/src/components/contract_runtime/operations.rs b/node/src/components/contract_runtime/operations.rs index bcd62c2903..52e45f6609 100644 --- a/node/src/components/contract_runtime/operations.rs +++ b/node/src/components/contract_runtime/operations.rs @@ -3,51 +3,48 @@ use std::{collections::BTreeMap, convert::TryInto, sync::Arc, time::Instant}; use itertools::Itertools; use tracing::{debug, error, info, trace, warn}; -use casper_execution_engine::engine_state::{ - self, - execution_result::{ExecutionResultAndMessages, ExecutionResults}, - DeployItem, ExecuteRequest, ExecutionEngineV1, ExecutionResult as EngineExecutionResult, -}; +use casper_execution_engine::engine_state::{ExecutionEngineV1, WasmV1Request, WasmV1Result}; use casper_storage::{ block_store::types::ApprovalsHashes, data_access_layer::{ - AuctionMethod, BiddingRequest, BiddingResult, BlockRewardsRequest, BlockRewardsResult, - DataAccessLayer, EraValidatorsRequest, EraValidatorsResult, EvictItem, FeeRequest, - FeeResult, FlushRequest, PruneRequest, PruneResult, StepRequest, StepResult, - TransferRequest, TransferResult, + balance::BalanceHandling, AuctionMethod, BalanceHoldRequest, BalanceIdentifier, + BalanceRequest, BiddingRequest, BlockRewardsRequest, BlockRewardsResult, DataAccessLayer, + EraValidatorsRequest, EraValidatorsResult, EvictItem, FeeRequest, FeeResult, FlushRequest, + HandlePaymentMode, HandlePaymentRequest, InsufficientBalanceHandling, PruneRequest, + PruneResult, StepRequest, StepResult, TransferRequest, }, - global_state::{ - error::Error as GlobalStateError, - state::{ - lmdb::LmdbGlobalState, scratch::ScratchGlobalState, CommitProvider, ScratchProvider, - StateProvider, StateReader, - }, + global_state::state::{ + lmdb::LmdbGlobalState, scratch::ScratchGlobalState, CommitProvider, ScratchProvider, + StateProvider, StateReader, }, system::runtime_native::Config as NativeRuntimeConfig, }; + use casper_types::{ - binary_port::SpeculativeExecutionResult, bytesrepr::{self, ToBytes, U32_SERIALIZED_LENGTH}, - contract_messages::Messages, - execution::{Effects, ExecutionResult, ExecutionResultV2, TransformKindV2, TransformV2}, - ApprovalsHash, BlockV2, CLValue, Chainspec, ChecksumRegistry, DeployHash, Digest, EraEndV2, - EraId, Key, ProtocolVersion, PublicKey, Transaction, U512, + execution::{Effects, ExecutionResult, TransformKindV2, TransformV2}, + system::mint::BalanceHoldAddrTag, + BlockHeader, BlockTime, BlockV2, CLValue, CategorizedTransaction, Chainspec, ChecksumRegistry, + Digest, EraEndV2, EraId, FeeHandling, Gas, GasLimited, HoldsEpoch, Key, Motes, ProtocolVersion, + PublicKey, Transaction, TransactionCategory, U512, }; +use super::{ + types::{SpeculativeExecutionResult, StepOutcome}, + utils::{self, calculate_prune_eras}, + BlockAndExecutionArtifacts, BlockExecutionError, ExecutionPreState, Metrics, + APPROVALS_CHECKSUM_NAME, EXECUTION_RESULTS_CHECKSUM_NAME, +}; use crate::{ - components::{ - contract_runtime::{ - error::BlockExecutionError, types::StepEffectsAndUpcomingEraValidators, - BlockAndExecutionResults, ExecutionPreState, Metrics, SpeculativeExecutionState, - APPROVALS_CHECKSUM_NAME, EXECUTION_RESULTS_CHECKSUM_NAME, - }, - fetcher::FetchItem, - }, - contract_runtime::utils::calculate_prune_eras, + components::fetcher::FetchItem, + contract_runtime::types::ExecutionArtifactBuilder, types::{self, Chunkable, ExecutableBlock, InternalEraReport}, }; -use super::ExecutionArtifact; +const ACCOUNT_SESSION: bool = true; +const DIRECT_CONTRACT: bool = !ACCOUNT_SESSION; +const STANDARD_PAYMENT: bool = true; +const CUSTOM_PAYMENT: bool = !STANDARD_PAYMENT; /// Executes a finalized block. #[allow(clippy::too_many_arguments)] @@ -61,7 +58,7 @@ pub fn execute_finalized_block( key_block_height_for_activation_point: u64, current_gas_price: u8, next_era_gas_price: Option, -) -> Result { +) -> Result { if executable_block.height != execution_pre_state.next_block_height() { return Err(BlockExecutionError::WrongBlockHeight { executable_block: Box::new(executable_block), @@ -85,56 +82,427 @@ pub fn execute_finalized_block( let parent_seed = execution_pre_state.parent_seed(); let mut state_root_hash = pre_state_root_hash; - let mut execution_artifacts: Vec = - Vec::with_capacity(executable_block.transactions.len()); - let block_time = executable_block.timestamp.millis(); + let mut artifacts = Vec::with_capacity(executable_block.transactions.len()); + let block_time = BlockTime::new(executable_block.timestamp.millis()); + let holds_epoch = + HoldsEpoch::from_block_time(block_time, chainspec.core_config.balance_hold_interval); + let balance_handling = BalanceHandling::Available { holds_epoch }; + let proposer = executable_block.proposer.clone(); + let start = Instant::now(); - let txn_ids = executable_block + + let scratch_state = data_access_layer.get_scratch_global_state(); + + let transaction_ids = executable_block .transactions .iter() .map(Transaction::fetch_id) .collect_vec(); - let approvals_checksum = types::compute_approvals_checksum(txn_ids.clone()) - .map_err(BlockExecutionError::FailedToComputeApprovalsChecksum)?; - let approvals_hashes: Vec = - txn_ids.into_iter().map(|id| id.approvals_hash()).collect(); + let insufficient_balance_handling = InsufficientBalanceHandling::HoldRemaining; - let scratch_state = data_access_layer.get_scratch_global_state(); - let mut effects = Effects::new(); + for transaction in executable_block.transactions { + let mut artifact_builder = ExecutionArtifactBuilder::new(&transaction); + + let initiator_addr = transaction.initiator_addr(); + let transaction_hash = transaction.hash(); + let runtime_args = transaction.session_args().clone(); + let entry_point = transaction.entry_point(); + let authorization_keys = transaction.authorization_keys(); + + // there are three separate mote / gas / token values and it is important to not mix them up + // we solve for halting state using a `gas limit` which is the maximum amount of + // computation we will allow a given transaction to consume. the transaction itself + // provides a function to determine this if provided with the current cost tables + // + // next there is the actual cost, i.e. how much we charge for that computation + // this is calculated by multiplying the gas limit by the current `gas_price` + // gas price has a floor of 1, and the ceiling is configured in the chainspec + // NOTE: when the gas price is 1, the gas limit and the cost are coincidentally equal + // because x == x * 1; thus it is recommended to run tests with gas price >1 to + // avoid being confused by this + // + // the third important value is the amount of computation consumed by executing a + // transaction for native transactions there is no wasm and the consumed always + // equals the limit for bytecode / wasm based transactions the consumed is based on + // what opcodes were executed in such cases, consumed can range from >0 to + // <=gas_limit. consumed is determined after execution and is important for payment + // post processing + + // NOTE: this is the allowed computation limit (gas limit) + let gas_limit = match transaction.gas_limit(chainspec) { + Ok(gas) => gas, + Err(ite) => { + debug!(%transaction_hash, %ite, "invalid transaction (gas limit)"); + artifact_builder.with_invalid_transaction(&ite); + artifacts.push(artifact_builder.build()); + continue; + } + }; + artifact_builder.with_gas_limit(gas_limit); + + // NOTE: this is the actual adjusted cost that we charge for (gas limit * gas price) + let cost = match transaction.gas_cost(chainspec, current_gas_price) { + Ok(motes) => motes.value(), + Err(ite) => { + debug!(%transaction_hash, "invalid transaction (motes conversion)"); + artifact_builder.with_invalid_transaction(&ite); + artifacts.push(artifact_builder.build()); + continue; + } + }; + artifact_builder.with_added_cost(cost); + + let balance_identifier = { + let is_account_session = transaction.is_account_session(); + let is_standard_payment = transaction.is_standard_payment(); + // if standard payment & is session based...use account main purse + // if standard payment & is targeting a contract + // load contract & check entry point, if it pays use contract main purse + // if custom payment, attempt execute custom payment + // if custom payment fails, take remaining balance up to amount + // currently contracts cannot provide custom payment, but possible future use + match (is_account_session, is_standard_payment) { + (ACCOUNT_SESSION, STANDARD_PAYMENT) => { + // this is the typical scenario; the initiating account pays using its main + // purse + trace!(%transaction_hash, "account session with standard payment"); + initiator_addr.clone().into() + } + (ACCOUNT_SESSION, CUSTOM_PAYMENT) => { + // the initiating account will pay, but wants to do so with a different purse or + // in a custom way. If anything goes wrong, penalize the sender, do not execute + let custom_payment_gas_limit = Gas::new( + // TODO: this should have it's own chainspec value; in the meantime + // using a multiple of a small value. + chainspec.transaction_config.native_transfer_minimum_motes * 5, + ); + let pay_result = match WasmV1Request::new_custom_payment( + state_root_hash, + block_time, + custom_payment_gas_limit, + &transaction, + ) { + Ok(pay_request) => execution_engine_v1.execute(&scratch_state, pay_request), + Err(error) => { + WasmV1Result::invalid_executable_item(custom_payment_gas_limit, error) + } + }; + let balance_identifier = { + if pay_result.error().is_some() { + BalanceIdentifier::PenalizedAccount(initiator_addr.account_hash()) + } else { + BalanceIdentifier::Payment + } + }; + state_root_hash = + scratch_state.commit(state_root_hash, pay_result.effects().clone())?; + artifact_builder + .with_wasm_v1_result(pay_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + trace!(%transaction_hash, ?balance_identifier, "account session with custom payment"); + balance_identifier + } + (DIRECT_CONTRACT, STANDARD_PAYMENT) => { + // TODO: get the contract, check the entry point indicated in the transaction + // if the contract pays for itself, use its main purse + // <-- contracts paying for things wire up goes here --> + // use scratch_state to read the contract & check it here + // if the contract does not exist, the entrypoint does not exist, + // the entrypoint does not pay for itself, and every other sad path + // outcome... penalize the sender, do not execute + debug!("direct contract invocation is currently unsupported; penalize the account that sent it."); + BalanceIdentifier::PenalizedAccount(initiator_addr.account_hash()) + } + (DIRECT_CONTRACT, CUSTOM_PAYMENT) => { + // currently not supported. penalize the sender, do not execute. + warn!("direct contract invocation is currently unsupported; penalize the account that sent it."); + BalanceIdentifier::PenalizedAccount(initiator_addr.account_hash()) + } + } + }; + + let initial_balance_result = scratch_state.balance(BalanceRequest::new( + state_root_hash, + protocol_version, + balance_identifier.clone(), + balance_handling, + )); + + let allow_execution = { + let is_not_penalized = !balance_identifier.is_penalty(); + let sufficient_balance = initial_balance_result.is_sufficient(cost); + trace!(%transaction_hash, ?sufficient_balance, ?is_not_penalized, "payment preprocessing"); + is_not_penalized && sufficient_balance + }; + + if allow_execution { + let category = transaction.category(); + trace!(%transaction_hash, ?category, "eligible for execution"); + match category { + TransactionCategory::Mint => { + let transfer_result = + scratch_state.transfer(TransferRequest::with_runtime_args( + native_runtime_config.clone(), + state_root_hash, + holds_epoch, + protocol_version, + transaction_hash, + initiator_addr, + authorization_keys, + runtime_args, + )); + let consumed = gas_limit; + state_root_hash = + scratch_state.commit(state_root_hash, transfer_result.effects().clone())?; + artifact_builder + .with_added_consumed(consumed) + .with_transfer_result(transfer_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + TransactionCategory::Auction => { + match AuctionMethod::from_parts( + entry_point, + &runtime_args, + holds_epoch, + chainspec, + ) { + Ok(auction_method) => { + let bidding_result = scratch_state.bidding(BiddingRequest::new( + native_runtime_config.clone(), + state_root_hash, + protocol_version, + transaction_hash, + initiator_addr, + authorization_keys, + auction_method, + )); + let consumed = gas_limit; + state_root_hash = scratch_state + .commit(state_root_hash, bidding_result.effects().clone())?; + artifact_builder + .with_added_consumed(consumed) + .with_bidding_result(bidding_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + Err(ame) => { + error!( + %transaction_hash, + ?ame, + "failed to determine auction method" + ); + artifact_builder.with_auction_method_error(&ame); + } + }; + } + TransactionCategory::Standard | TransactionCategory::InstallUpgrade => { + match WasmV1Request::new_session( + state_root_hash, + block_time, + gas_limit, + &transaction, + ) { + Ok(wasm_v1_request) => { + trace!(%transaction_hash, ?category, ?wasm_v1_request, "able to get wasm v1 request"); + let wasm_v1_result = + execution_engine_v1.execute(&scratch_state, wasm_v1_request); + trace!(%transaction_hash, ?category, ?wasm_v1_result, "able to get wasm v1 result"); + state_root_hash = scratch_state + .commit(state_root_hash, wasm_v1_result.effects().clone())?; + // note: consumed is scraped from wasm_v1_result along w/ other fields + artifact_builder + .with_wasm_v1_result(wasm_v1_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + Err(ire) => { + debug!(%transaction_hash, ?category, ?ire, "unable to get wasm v1 request"); + artifact_builder.with_invalid_wasm_v1_request(&ire); + } + }; + } + } + } else { + debug!(%transaction_hash, "not eligible for execution"); + } + + let fee_handling = chainspec.core_config.fee_handling; + // handle payment per the chainspec determined fee setting + match fee_handling { + FeeHandling::NoFee => { + // in this mode, a hold for full cost is placed on the payer's purse. + let handle_payment_request = HandlePaymentRequest::new( + native_runtime_config.clone(), + state_root_hash, + protocol_version, + transaction_hash, + HandlePaymentMode::clear_holds(balance_identifier.clone(), holds_epoch), + ); + let handle_payment_result = scratch_state.handle_payment(handle_payment_request); + state_root_hash = scratch_state + .commit(state_root_hash, handle_payment_result.effects().clone())?; + artifact_builder + .with_handle_payment_result(&handle_payment_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + let hold_result = scratch_state.balance_hold(BalanceHoldRequest::new( + state_root_hash, + protocol_version, + balance_identifier, + BalanceHoldAddrTag::Gas, + cost, + block_time, + holds_epoch, + insufficient_balance_handling, + )); + state_root_hash = + scratch_state.commit(state_root_hash, hold_result.effects().clone())?; + artifact_builder + .with_balance_hold_result(&hold_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + FeeHandling::PayToProposer => { + // in this mode, the consumed gas is paid as a fee to the block proposer + let consumed = Gas::new(artifact_builder.consumed()); + let handle_payment_request = HandlePaymentRequest::new( + native_runtime_config.clone(), + state_root_hash, + protocol_version, + transaction_hash, + HandlePaymentMode::finalize( + gas_limit.value(), + current_gas_price, + cost, + consumed.value(), + balance_identifier, + BalanceIdentifier::Public(*(proposer.clone())), + holds_epoch, + ), + ); + let handle_payment_result = scratch_state.handle_payment(handle_payment_request); + state_root_hash = scratch_state + .commit(state_root_hash, handle_payment_result.effects().clone())?; + artifact_builder + .with_handle_payment_result(&handle_payment_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + FeeHandling::Accumulate => { + // in this mode, consumed gas is accumulated into a single purse for later + // distribution + let consumed = Gas::new(artifact_builder.consumed()); + let amount = Motes::from_gas(consumed, current_gas_price) + .map(|x| x.value()) + .unwrap_or_else(U512::zero); + let handle_payment_request = HandlePaymentRequest::new( + native_runtime_config.clone(), + state_root_hash, + protocol_version, + transaction_hash, + HandlePaymentMode::finalize( + gas_limit.value(), + current_gas_price, + cost, + amount, + balance_identifier, + BalanceIdentifier::Accumulate, + holds_epoch, + ), + ); + let handle_payment_result = scratch_state.handle_payment(handle_payment_request); + state_root_hash = scratch_state + .commit(state_root_hash, handle_payment_result.effects().clone())?; + artifact_builder + .with_handle_payment_result(&handle_payment_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + FeeHandling::Burn => { + let consumed = Gas::new(artifact_builder.consumed()); + let amount = Motes::from_gas(consumed, current_gas_price).map(|x| x.value()); + let handle_payment_request = HandlePaymentRequest::new( + native_runtime_config.clone(), + state_root_hash, + protocol_version, + transaction_hash, + HandlePaymentMode::burn(balance_identifier, amount), + ); + let handle_payment_result = scratch_state.handle_payment(handle_payment_request); + state_root_hash = scratch_state + .commit(state_root_hash, handle_payment_result.effects().clone())?; + artifact_builder + .with_handle_payment_result(&handle_payment_result) + .map_err(|_| BlockExecutionError::RootNotFound(state_root_hash))?; + } + } + + if let Some(metrics) = metrics.as_ref() { + metrics + .commit_effects + .observe(start.elapsed().as_secs_f64()); + } + artifacts.push(artifact_builder.build()); + } + + // calculate and store checksums for approvals and execution effects across the transactions in + // the block we do this so that the full set of approvals and the full set of effect meta + // data can be verified if necessary for a given block. the block synchronizer in particular + // depends on the existence of such checksums. + let txns_approvals_hashes = { + let approvals_checksum = types::compute_approvals_checksum(transaction_ids.clone()) + .map_err(BlockExecutionError::FailedToComputeApprovalsChecksum)?; + let execution_results_checksum = compute_execution_results_checksum( + artifacts.iter().map(|artifact| &artifact.execution_result), + )?; + let mut checksum_registry = ChecksumRegistry::new(); + checksum_registry.insert(APPROVALS_CHECKSUM_NAME, approvals_checksum); + checksum_registry.insert(EXECUTION_RESULTS_CHECKSUM_NAME, execution_results_checksum); + + let mut effects = Effects::new(); + effects.push(TransformV2::new( + Key::ChecksumRegistry, + TransformKindV2::Write( + CLValue::from_t(checksum_registry) + .map_err(BlockExecutionError::ChecksumRegistryToCLValue)? + .into(), + ), + )); + scratch_state.commit(state_root_hash, effects)?; + transaction_ids + .into_iter() + .map(|id| id.approvals_hash()) + .collect() + }; - // Pay out fees, if relevant. + // Pay out block fees, if relevant. This auto-commits { let fee_req = FeeRequest::new( native_runtime_config.clone(), state_root_hash, protocol_version, block_time, + holds_epoch, ); match scratch_state.distribute_fees(fee_req) { FeeResult::RootNotFound => { - return Err(BlockExecutionError::RootNotFound(state_root_hash)) + return Err(BlockExecutionError::RootNotFound(state_root_hash)); } FeeResult::Failure(fer) => return Err(BlockExecutionError::DistributeFees(fer)), FeeResult::Success { - //transfers: fee_transfers, - post_state_hash, - .. + post_state_hash, .. } => { - //transfers.extend(fee_transfers); state_root_hash = post_state_hash; - // TODO: looks like effects & transfer records are associated with the - // ExecutionResult struct which assumes they were caused by a - // deploy. however, systemic operations produce effects and transfer - // records also. } } } + // Update exec_block metric BEFORE determining per era things such as era rewards and step. + // the commit_step function handles the metrics for step + if let Some(metrics) = metrics.as_ref() { + metrics.exec_block.observe(start.elapsed().as_secs_f64()); + } + // Pay out ̶b̶l̶o̶c̶k̶ e͇r͇a͇ rewards // NOTE: despite the name, these rewards are currently paid out per ERA not per BLOCK // at one point, they were going to be paid out per block (and might be in the future) - // but it ended up settling on per era. the behavior is driven by Some / None as sent - // thus if in future calling logic passes rewards per block it should just work as is. + // but it ended up settling on per era. the behavior is driven by Some / None + // thus if in future the calling logic passes rewards per block it should just work as is. + // This auto-commits. if let Some(rewards) = &executable_block.rewards { let rewards_req = BlockRewardsRequest::new( native_runtime_config.clone(), @@ -145,10 +513,10 @@ pub fn execute_finalized_block( ); match scratch_state.distribute_block_rewards(rewards_req) { BlockRewardsResult::RootNotFound => { - return Err(BlockExecutionError::RootNotFound(state_root_hash)) + return Err(BlockExecutionError::RootNotFound(state_root_hash)); } BlockRewardsResult::Failure(bre) => { - return Err(BlockExecutionError::DistributeBlockRewards(bre)) + return Err(BlockExecutionError::DistributeBlockRewards(bre)); } BlockRewardsResult::Success { post_state_hash, .. @@ -158,206 +526,9 @@ pub fn execute_finalized_block( } } - for transaction in executable_block.transactions { - /* - In the go forward, see deploy and transactions, the new transactions specify - the target lane in the block, currently there are 4, staking, transfer, install - and everything else. Legacy deploy is either a native transfer which is one of the lanes - and everything else is not specified and get the default older behavior. The price - for all native transfer is set in chainspec. - - What price does it go in, what slot, what is the multiplier, and thats the price - Then we check the balance for the payer, and put a hold for that amount. - And if we can't put the hold we can't engage the virtual machine - Record the error and move on, and charge the penalty payment if any - - This happens here before any engagement of the virtual machine. - */ - let transaction_hash = transaction.hash(); - if transaction.is_native_mint() { - // native transfers are routed to the data provider - let authorization_keys = transaction.authorization_keys(); - let transfer_req = TransferRequest::with_runtime_args( - native_runtime_config.clone(), - state_root_hash, - block_time, - protocol_version, - transaction_hash, - transaction.initiator_addr().account_hash(), - authorization_keys, - transaction.session_args().clone(), - U512::zero(), /* <-- this should be from chainspec cost table */ - ); - //NOTE: native mint interactions auto-commit - let transfer_result = scratch_state.transfer(transfer_req); - trace!( - ?transaction_hash, - ?transfer_result, - "native transfer result" - ); - match transfer_result { - TransferResult::RootNotFound => { - return Err(BlockExecutionError::RootNotFound(state_root_hash)); - } - TransferResult::Failure(transfer_error) => { - let artifact = ExecutionArtifact::new( - transaction_hash, - transaction.header(), - ExecutionResult::V2(ExecutionResultV2::Failure { - effects: Effects::new(), - cost: U512::zero(), - transfers: vec![], - error_message: format!("{:?}", transfer_error), - }), - Messages::default(), - ); - execution_artifacts.push(artifact); - debug!(%transfer_error); - // a failure does not auto commit - continue; - } - TransferResult::Success { - effects: transfer_effects, - transfers, - .. - } => { - effects.append(transfer_effects.clone()); - let artifact = ExecutionArtifact::new( - transaction_hash, - transaction.header(), - ExecutionResult::V2(ExecutionResultV2::Success { - effects: transfer_effects, - cost: U512::zero(), - transfers, - }), - Messages::default(), - ); - execution_artifacts.push(artifact); - } - } - continue; - } - if transaction.is_native_auction() { - let args = transaction.session_args(); - let entry_point = transaction.entry_point(); - let auction_method = match AuctionMethod::from_parts(entry_point, args, chainspec) { - Ok(auction_method) => auction_method, - Err(_) => { - error!(%transaction_hash, "failed to resolve auction method"); - continue; // skip to next record - } - }; - let authorization_keys = transaction.authorization_keys(); - let bidding_req = BiddingRequest::new( - native_runtime_config.clone(), - state_root_hash, - block_time, - protocol_version, - transaction_hash, - transaction.initiator_addr().account_hash(), - authorization_keys, - auction_method, - ); - - //NOTE: native mint interactions auto-commit - let bidding_result = scratch_state.bidding(bidding_req); - trace!(?transaction_hash, ?bidding_result, "native auction result"); - match bidding_result { - BiddingResult::RootNotFound => { - return Err(BlockExecutionError::RootNotFound(state_root_hash)) - } - BiddingResult::Success { - post_state_hash, .. - } => { - // we need a way to capture the effects from this without double committing - state_root_hash = post_state_hash; - } - BiddingResult::Failure(tce) => { - debug!(%tce); - continue; - } - } - } - - let (deploy_hash, deploy) = match transaction { - Transaction::Deploy(deploy) => { - let deploy_hash = *deploy.hash(); - (deploy_hash, deploy) - } - Transaction::V1(_) => continue, - }; - - let deploy_header = deploy.header().clone(); - let execute_request = ExecuteRequest::new( - state_root_hash, - block_time, - vec![DeployItem::from(deploy)], - protocol_version, - PublicKey::clone(&executable_block.proposer), - ); - - let exec_result = execute( - &scratch_state, - execution_engine_v1, - metrics.clone(), - execute_request, - )?; - - trace!(?deploy_hash, ?exec_result, "transaction execution result"); - // As for now a given state is expected to exist. - let (state_hash, execution_result, messages) = commit_execution_results( - &scratch_state, - metrics.clone(), - state_root_hash, - deploy_hash, - exec_result, - )?; - execution_artifacts.push(ExecutionArtifact::deploy( - deploy_hash, - deploy_header, - execution_result, - messages, - )); - state_root_hash = state_hash; - } - - // handle checksum registry - let approvals_hashes = { - let mut checksum_registry = ChecksumRegistry::new(); - - checksum_registry.insert(APPROVALS_CHECKSUM_NAME, approvals_checksum); - - // Write the deploy approvals' and execution results' checksums to global state. - let execution_results_checksum = compute_execution_results_checksum( - execution_artifacts - .iter() - .map(|artifact| &artifact.execution_result), - )?; - checksum_registry.insert(EXECUTION_RESULTS_CHECKSUM_NAME, execution_results_checksum); - - effects.push(TransformV2::new( - Key::ChecksumRegistry, - TransformKindV2::Write( - CLValue::from_t(checksum_registry) - .map_err(BlockExecutionError::ChecksumRegistryToCLValue)? - .into(), - ), - )); - - approvals_hashes - }; - - scratch_state.commit(state_root_hash, effects)?; - - if let Some(metrics) = metrics.as_ref() { - metrics.exec_block.observe(start.elapsed().as_secs_f64()); - } - - // If the finalized block has an era report, run the auction contract and get the upcoming era - // validators. - let maybe_step_effects_and_upcoming_era_validators = if let Some(era_report) = - &executable_block.era_report - { + // if era report is some, this is a switch block. a series of end-of-era extra processing must + // transpire before this block is entirely finished. + let step_outcome = if let Some(era_report) = &executable_block.era_report { let step_effects = match commit_step( native_runtime_config, &scratch_state, @@ -369,10 +540,17 @@ pub fn execute_finalized_block( executable_block.era_id.successor(), ) { StepResult::RootNotFound => { - return Err(BlockExecutionError::RootNotFound(state_root_hash)) + return Err(BlockExecutionError::RootNotFound(state_root_hash)); } StepResult::Failure(err) => return Err(BlockExecutionError::Step(err)), - StepResult::Success { effects, .. } => effects, + StepResult::Success { + effects, + post_state_hash, + .. + } => { + state_root_hash = post_state_hash; + effects + } }; state_root_hash = data_access_layer.write_scratch_to_db(state_root_hash, scratch_state)?; @@ -381,12 +559,12 @@ pub fn execute_finalized_block( let era_validators_result = data_access_layer.era_validators(era_validators_req); let upcoming_era_validators = match era_validators_result { - EraValidatorsResult::AuctionNotFound => { - panic!("auction not found"); - } EraValidatorsResult::RootNotFound => { panic!("root not found"); } + EraValidatorsResult::AuctionNotFound => { + panic!("auction not found"); + } EraValidatorsResult::ValueNotFound(msg) => { panic!("validator snapshot not found: {}", msg); } @@ -396,7 +574,7 @@ pub fn execute_finalized_block( EraValidatorsResult::Success { era_validators } => era_validators, }; - Some(StepEffectsAndUpcomingEraValidators { + Some(StepOutcome { step_effects, upcoming_era_validators, }) @@ -407,15 +585,8 @@ pub fn execute_finalized_block( None }; - // Flush once, after all deploys have been executed. - let flush_req = FlushRequest::new(); - let flush_result = data_access_layer.flush(flush_req); - if let Err(gse) = flush_result.as_error() { - error!("failed to flush lmdb"); - return Err(BlockExecutionError::Lmdb(gse)); - } - - // Pruning + // Pruning -- this is orthogonal to the contents of the block, but we deliberately do it + // at the end to avoid an read ordering issue during block execution. if let Some(previous_block_height) = executable_block.height.checked_sub(1) { if let Some(keys_to_prune) = calculate_prune_eras( activation_point_era_id, @@ -475,9 +646,18 @@ pub fn execute_finalized_block( } } + // Flush once, after all data mutation. + let flush_req = FlushRequest::new(); + let flush_result = data_access_layer.flush(flush_req); + if let Err(gse) = flush_result.as_error() { + error!("failed to flush lmdb"); + return Err(BlockExecutionError::Lmdb(gse)); + } + + // the rest of this is post process, picking out data bits to return to caller let next_era_id = executable_block.era_id.successor(); let maybe_next_era_validator_weights: Option<(BTreeMap, u8)> = - match maybe_step_effects_and_upcoming_era_validators.as_ref() { + match step_outcome.as_ref() { None => None, Some(effects_and_validators) => { match effects_and_validators @@ -539,7 +719,7 @@ pub fn execute_finalized_block( executable_block.era_id, executable_block.height, protocol_version, - (*executable_block.proposer).clone(), + (*proposer).clone(), executable_block.mint, executable_block.auction, executable_block.install_upgrade, @@ -548,161 +728,64 @@ pub fn execute_finalized_block( current_gas_price, )); - let tc = match data_access_layer.tracking_copy(state_root_hash) { - Ok(Some(tc)) => tc, - Ok(None) => return Err(BlockExecutionError::RootNotFound(state_root_hash)), - Err(gse) => return Err(BlockExecutionError::Lmdb(gse)), + // TODO: this should just use the data_access_layer.query mechanism to avoid + // leaking data provisioning abstraction + let proof_of_checksum_registry = match data_access_layer.tracking_copy(state_root_hash)? { + Some(tc) => match tc.reader().read_with_proof(&Key::ChecksumRegistry)? { + Some(proof) => proof, + None => return Err(BlockExecutionError::MissingChecksumRegistry), + }, + None => return Err(BlockExecutionError::RootNotFound(state_root_hash)), }; - let approvals_hashes = { - let proof_of_checksum_registry = match tc.reader().read_with_proof(&Key::ChecksumRegistry) { - Ok(Some(proof)) => proof, - Ok(None) => return Err(BlockExecutionError::MissingChecksumRegistry), - Err(gse) => return Err(BlockExecutionError::Lmdb(gse)), - }; - - Box::new(ApprovalsHashes::new( - *block.hash(), - approvals_hashes, - proof_of_checksum_registry, - )) - }; + let approvals_hashes = Box::new(ApprovalsHashes::new( + *block.hash(), + txns_approvals_hashes, + proof_of_checksum_registry, + )); - Ok(BlockAndExecutionResults { + Ok(BlockAndExecutionArtifacts { block, approvals_hashes, - execution_results: execution_artifacts, - maybe_step_effects_and_upcoming_era_validators, + execution_artifacts: artifacts, + step_outcome, }) } -/// Commits the execution results. -fn commit_execution_results( - scratch_state: &ScratchGlobalState, - metrics: Option>, - state_root_hash: Digest, - deploy_hash: DeployHash, - execution_results: ExecutionResults, -) -> Result<(Digest, ExecutionResult, Messages), BlockExecutionError> { - let ee_execution_result = execution_results - .into_iter() - .exactly_one() - .map_err(|_| BlockExecutionError::MoreThanOneExecutionResult)?; - - let effects = match &ee_execution_result { - EngineExecutionResult::Success { effects, cost, .. } => { - // We do want to see the deploy hash and cost in the logs. - // We don't need to see the effects in the logs. - debug!(?deploy_hash, %cost, "execution succeeded"); - effects.clone() - } - EngineExecutionResult::Failure { - error, - effects, - cost, - .. - } => { - // Failure to execute a contract is a user error, not a system error. - // We do want to see the deploy hash, error, and cost in the logs. - // We don't need to see the effects in the logs. - debug!(?deploy_hash, ?error, %cost, "execution failure"); - effects.clone() - } - }; - let new_state_root = commit_transforms(scratch_state, metrics, state_root_hash, effects)?; - let ExecutionResultAndMessages { - execution_result, - messages, - } = ExecutionResultAndMessages::from(ee_execution_result); - let versioned_execution_result = ExecutionResult::from(execution_result); - Ok((new_state_root, versioned_execution_result, messages)) -} - -fn commit_transforms( - scratch_state: &ScratchGlobalState, - metrics: Option>, - state_root_hash: Digest, - effects: Effects, -) -> Result { - trace!(?state_root_hash, ?effects, "commit"); - let start = Instant::now(); - let result = scratch_state.commit(state_root_hash, effects); - if let Some(metrics) = metrics { - metrics.apply_effect.observe(start.elapsed().as_secs_f64()); - } - trace!(?result, "commit result"); - result -} - /// Execute the transaction without committing the effects. /// Intended to be used for discovery operations on read-only nodes. /// /// Returns effects of the execution. -pub fn speculatively_execute( +pub(super) fn speculatively_execute( state_provider: &S, + chainspec: &Chainspec, execution_engine_v1: &ExecutionEngineV1, - execution_state: SpeculativeExecutionState, - deploy: DeployItem, -) -> Result + block_header: BlockHeader, + transaction: Transaction, +) -> SpeculativeExecutionResult where S: StateProvider, { - let SpeculativeExecutionState { - state_root_hash, - block_time, - protocol_version, - } = execution_state; - let deploy_hash = deploy.deploy_hash; - let execute_request = ExecuteRequest::new( - state_root_hash, - block_time.millis(), - vec![deploy], - protocol_version, - PublicKey::System, - ); - let results = execute(state_provider, execution_engine_v1, None, execute_request); - results.map(|mut execution_results| { - let len = execution_results.len(); - if len != 1 { - warn!( - ?deploy_hash, - "got more ({}) execution results from a single transaction", len - ); - SpeculativeExecutionResult::new(None) - } else { - // We know it must be 1, we could unwrap and then wrap - // with `Some(_)` but `pop_front` already returns an `Option`. - // We need to transform the `engine_state::ExecutionResult` into - // `casper_types::ExecutionResult` as well. - SpeculativeExecutionResult::new(execution_results.pop_front().map(|result| { - let ExecutionResultAndMessages { - execution_result, - messages, - } = result.into(); - - (execution_result, messages) - })) + let state_root_hash = block_header.state_root_hash(); + let block_time = block_header + .timestamp() + .saturating_add(chainspec.core_config.minimum_block_time); + let gas_limit = match transaction.gas_limit(chainspec) { + Ok(gas_limit) => gas_limit, + Err(_) => { + return SpeculativeExecutionResult::invalid_gas_limit(transaction); } - }) -} - -fn execute( - state_provider: &S, - execution_engine_v1: &ExecutionEngineV1, - metrics: Option>, - execute_request: ExecuteRequest, -) -> Result -where - S: StateProvider, -{ - trace!(?execute_request, "execute"); - let start = Instant::now(); - let result = execution_engine_v1.exec(state_provider, execute_request); - if let Some(metrics) = metrics { - metrics.run_execute.observe(start.elapsed().as_secs_f64()); - } - trace!(?result, "execute result"); - result + }; + let wasm_v1_result = match WasmV1Request::new_session( + *state_root_hash, + block_time.into(), + gas_limit, + &transaction, + ) { + Ok(wasm_v1_request) => execution_engine_v1.execute(state_provider, wasm_v1_request), + Err(error) => WasmV1Result::invalid_executable_item(gas_limit, error), + }; + SpeculativeExecutionResult::WasmV1(utils::spec_exec_from_wasm_v1_result(wasm_v1_result)) } #[allow(clippy::too_many_arguments)] diff --git a/node/src/components/contract_runtime/tests.rs b/node/src/components/contract_runtime/tests.rs index 767c9cf88c..576089a2d9 100644 --- a/node/src/components/contract_runtime/tests.rs +++ b/node/src/components/contract_runtime/tests.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use std::{collections::BTreeMap, iter, sync::Arc, time::Duration}; use derive_more::{Display, From}; use prometheus::Registry; @@ -8,7 +8,8 @@ use tempfile::TempDir; use casper_types::{ bytesrepr::Bytes, runtime_args, BlockHash, Chainspec, ChainspecRawBytes, Deploy, Digest, EraId, - ExecutableDeployItem, PublicKey, SecretKey, TimeDiff, Timestamp, TransactionCategory, U512, + ExecutableDeployItem, PublicKey, SecretKey, TimeDiff, Timestamp, Transaction, + TransactionCategory, TransactionConfig, U512, }; use super::*; @@ -102,6 +103,7 @@ impl reactor::Reactor for Reactor { RECENT_ERA_COUNT, Some(registry), false, + TransactionConfig::default(), ) .unwrap(); @@ -300,7 +302,7 @@ async fn should_not_set_shared_pre_state_to_lower_block_height() { }, }; - let txns: Vec = std::iter::repeat_with(|| { + let txns: Vec = iter::repeat_with(|| { let target_public_key = PublicKey::random(rng); let session = ExecutableDeployItem::Transfer { args: runtime_args! { @@ -394,6 +396,9 @@ async fn should_not_set_shared_pre_state_to_lower_block_height() { mod trie_chunking_tests { use std::sync::Arc; + use prometheus::Registry; + use tempfile::tempdir; + use casper_storage::global_state::{ state::{CommitProvider, StateProvider}, trie::Trie, @@ -405,19 +410,17 @@ mod trie_chunking_tests { global_state::Pointer, testing::TestRng, ActivationPoint, CLValue, Chainspec, ChunkWithProof, CoreConfig, Digest, EraId, Key, - ProtocolConfig, StoredValue, TimeDiff, DEFAULT_FEE_HANDLING, DEFAULT_REFUND_HANDLING, + ProtocolConfig, StoredValue, TimeDiff, DEFAULT_BALANCE_HOLD_INTERVAL, DEFAULT_FEE_HANDLING, + DEFAULT_REFUND_HANDLING, }; - use prometheus::Registry; - use tempfile::tempdir; + use super::{Config as ContractRuntimeConfig, ContractRuntime}; use crate::{ components::fetcher::FetchResponse, contract_runtime::ContractRuntimeError, types::{ChunkingError, TrieOrChunk, TrieOrChunkId, ValueOrChunk}, }; - use super::{Config as ContractRuntimeConfig, ContractRuntime}; - #[derive(Debug, Clone)] struct TestPair(Key, StoredValue); @@ -484,6 +487,7 @@ mod trie_chunking_tests { allow_unrestricted_transfers: true, fee_handling: DEFAULT_FEE_HANDLING, refund_handling: DEFAULT_REFUND_HANDLING, + balance_hold_interval: DEFAULT_BALANCE_HOLD_INTERVAL, ..CoreConfig::random(rng) }, wasm_config: Default::default(), diff --git a/node/src/components/contract_runtime/types.rs b/node/src/components/contract_runtime/types.rs index 9895274d2d..67ac8ee293 100644 --- a/node/src/components/contract_runtime/types.rs +++ b/node/src/components/contract_runtime/types.rs @@ -1,17 +1,25 @@ use std::{collections::BTreeMap, sync::Arc}; +use casper_types::{execution::PaymentInfo, InitiatorAddr, Transfer}; use datasize::DataSize; use serde::Serialize; +use casper_execution_engine::engine_state::{ + Error, InvalidRequest as InvalidWasmV1Request, WasmV1Result, +}; use casper_storage::{ - block_store::types::ApprovalsHashes, data_access_layer::EraValidatorsRequest, + block_store::types::ApprovalsHashes, + data_access_layer::{ + auction::AuctionMethodError, BalanceHoldResult, BiddingResult, EraValidatorsRequest, + HandlePaymentResult, TransferResult, + }, }; use casper_types::{ contract_messages::Messages, - execution::{Effects, ExecutionResult}, - BlockHash, BlockHeaderV2, BlockV2, DeployHash, DeployHeader, Digest, EraId, ProtocolVersion, - PublicKey, Timestamp, TransactionHash, TransactionHeader, TransactionV1Hash, - TransactionV1Header, U512, + execution::{Effects, ExecutionResult, ExecutionResultV2}, + BlockHash, BlockHeaderV2, BlockV2, Digest, EraId, Gas, InvalidDeploy, InvalidTransaction, + InvalidTransactionV1, ProtocolVersion, PublicKey, Transaction, TransactionHash, + TransactionHeader, U512, }; /// Request for validator weights for a specific era. @@ -54,9 +62,220 @@ impl From for EraValidatorsRequest { } } +#[derive(Clone, Debug)] +pub(crate) struct ExecutionArtifactBuilder { + effects: Effects, + hash: TransactionHash, + header: TransactionHeader, + error_message: Option, + messages: Messages, + transfers: Vec, + initiator: InitiatorAddr, + payment: Vec, + cost: U512, + limit: Gas, + consumed: Gas, +} + +impl ExecutionArtifactBuilder { + pub fn new(transaction: &Transaction) -> Self { + ExecutionArtifactBuilder { + effects: Effects::new(), + hash: transaction.hash(), + header: transaction.header(), + error_message: None, + transfers: vec![], + messages: Default::default(), + initiator: transaction.initiator_addr(), + payment: vec![], + cost: U512::zero(), + limit: Gas::zero(), + consumed: Gas::zero(), + } + } + + pub fn consumed(&self) -> U512 { + self.consumed.value() + } + + pub fn with_appended_transfers(&mut self, transfers: &mut Vec) -> &mut Self { + self.transfers.append(transfers); + self + } + + pub fn with_appended_effects(&mut self, effects: Effects) -> &mut Self { + self.effects.append(effects); + self + } + + pub fn with_appended_messages(&mut self, messages: &mut Messages) -> &mut Self { + self.messages.append(messages); + self + } + + pub fn with_wasm_v1_result(&mut self, wasm_v1_result: WasmV1Result) -> Result<&mut Self, ()> { + if let Some(Error::RootNotFound(_)) = wasm_v1_result.error() { + return Err(()); + } + if let (None, Some(err)) = (&self.error_message, wasm_v1_result.error()) { + self.error_message = Some(format!("{}", err)); + } + self.with_added_consumed(wasm_v1_result.consumed()) + .with_appended_messages(&mut wasm_v1_result.messages().clone()) + .with_appended_transfers(&mut wasm_v1_result.transfers().clone()) + .with_appended_effects(wasm_v1_result.effects().clone()); + Ok(self) + } + + pub fn with_handle_payment_result( + &mut self, + handle_payment_result: &HandlePaymentResult, + ) -> Result<&mut Self, ()> { + if let HandlePaymentResult::RootNotFound = handle_payment_result { + return Err(()); + } + if let (None, HandlePaymentResult::Failure(err)) = + (&self.error_message, handle_payment_result) + { + self.error_message = Some(format!("{}", err)); + // NOTE: if handle payment fails, we revert any prior effects. + // and only commit effects produced by handle payment (if any). + self.effects = handle_payment_result.effects(); + return Ok(self); + } + self.with_appended_effects(handle_payment_result.effects()); + Ok(self) + } + + pub fn with_balance_hold_result( + &mut self, + hold_result: &BalanceHoldResult, + ) -> Result<&mut Self, ()> { + if let BalanceHoldResult::RootNotFound = hold_result { + return Err(()); + } + if let (None, BalanceHoldResult::Failure(err)) = (&self.error_message, hold_result) { + self.error_message = Some(format!("{}", err)); + // NOTE: if holding balance fails, we revert any prior effects. + // and only commit effects produced by balance hold (if any). + self.effects = hold_result.effects(); + return Ok(self); + } + self.with_appended_effects(hold_result.effects()); + Ok(self) + } + + pub fn with_added_cost(&mut self, cost: U512) -> &mut Self { + self.cost = self.cost.saturating_add(cost); + self + } + + pub fn with_gas_limit(&mut self, limit: Gas) -> &mut Self { + self.limit = limit; + self + } + + pub fn with_added_consumed(&mut self, consumed: Gas) -> &mut Self { + self.consumed = self.consumed.saturating_add(consumed); + self + } + + pub fn with_invalid_transaction( + &mut self, + invalid_transaction: &InvalidTransaction, + ) -> &mut Self { + if self.error_message.is_none() { + self.error_message = Some(format!("{}", invalid_transaction)); + } + self + } + + pub fn with_invalid_wasm_v1_request( + &mut self, + invalid_request: &InvalidWasmV1Request, + ) -> &mut Self { + if self.error_message.is_none() { + self.error_message = Some(format!("{}", invalid_request)); + } + self + } + + pub fn with_auction_method_error( + &mut self, + auction_method_error: &AuctionMethodError, + ) -> &mut Self { + if self.error_message.is_none() { + self.error_message = Some(format!("{}", auction_method_error)); + } + self + } + + pub fn with_transfer_result( + &mut self, + transfer_result: TransferResult, + ) -> Result<&mut Self, ()> { + if let TransferResult::RootNotFound = transfer_result { + return Err(()); + } + if let (None, TransferResult::Failure(err)) = (&self.error_message, &transfer_result) { + self.error_message = Some(format!("{}", err)); + } + if let TransferResult::Success { + mut transfers, + effects, + } = transfer_result + { + self.with_appended_transfers(&mut transfers) + .with_appended_effects(effects); + } + Ok(self) + } + + pub fn with_bidding_result(&mut self, bidding_result: BiddingResult) -> Result<&mut Self, ()> { + if let BiddingResult::RootNotFound = bidding_result { + return Err(()); + } + if let (None, BiddingResult::Failure(err)) = (&self.error_message, &bidding_result) { + self.error_message = Some(format!("{}", err)); + } + if let BiddingResult::Success { effects, .. } = bidding_result { + self.with_appended_effects(effects); + } + Ok(self) + } + + #[allow(unused)] + pub fn with_initiator_addr(&mut self, initiator_addr: InitiatorAddr) -> &mut Self { + self.initiator = initiator_addr; + self + } + + //TODO: use this when payment breakdown is implemented. + #[allow(unused)] + pub fn with_appended_payment_info(&mut self, payment: &mut Vec) -> &mut Self { + self.payment.append(payment); + self + } + + pub(crate) fn build(self) -> ExecutionArtifact { + let result = ExecutionResultV2 { + effects: self.effects, + transfers: self.transfers, + initiator: self.initiator, + limit: self.limit, + consumed: self.consumed, + cost: self.cost, + payment: self.payment, + error_message: self.error_message, + }; + let execution_result = ExecutionResult::V2(result); + ExecutionArtifact::new(self.hash, self.header, execution_result, self.messages) + } +} + /// Effects from running step and the next era validators that are gathered when an era ends. #[derive(Clone, Debug, DataSize)] -pub(crate) struct StepEffectsAndUpcomingEraValidators { +pub(crate) struct StepOutcome { /// Validator sets for all upcoming eras that have already been determined. pub(crate) upcoming_era_validators: BTreeMap>, /// An [`Effects`] created by an era ending. @@ -66,7 +285,7 @@ pub(crate) struct StepEffectsAndUpcomingEraValidators { #[derive(Clone, Debug, DataSize, PartialEq, Eq, Serialize)] pub(crate) struct ExecutionArtifact { pub(crate) transaction_hash: TransactionHash, - pub(crate) header: TransactionHeader, + pub(crate) transaction_header: TransactionHeader, pub(crate) execution_result: ExecutionResult, pub(crate) messages: Messages, } @@ -74,42 +293,13 @@ pub(crate) struct ExecutionArtifact { impl ExecutionArtifact { pub(crate) fn new( transaction_hash: TransactionHash, - header: TransactionHeader, + transaction_header: TransactionHeader, execution_result: ExecutionResult, messages: Messages, ) -> Self { Self { transaction_hash, - header, - execution_result, - messages, - } - } - - pub(crate) fn deploy( - deploy_hash: DeployHash, - header: DeployHeader, - execution_result: ExecutionResult, - messages: Messages, - ) -> Self { - Self { - transaction_hash: TransactionHash::Deploy(deploy_hash), - header: TransactionHeader::Deploy(header), - execution_result, - messages, - } - } - - #[allow(unused)] - pub(crate) fn v1( - transaction_hash: TransactionV1Hash, - header: TransactionV1Header, - execution_result: ExecutionResult, - messages: Messages, - ) -> Self { - Self { - transaction_hash: TransactionHash::V1(transaction_hash), - header: TransactionHeader::V1(header), + transaction_header, execution_result, messages, } @@ -120,27 +310,35 @@ impl ExecutionArtifact { /// A [`Block`] that was the result of execution in the `ContractRuntime` along with any execution /// effects it may have. #[derive(Clone, Debug, DataSize)] -pub struct BlockAndExecutionResults { +pub struct BlockAndExecutionArtifacts { /// The [`Block`] the contract runtime executed. pub(crate) block: Arc, /// The [`ApprovalsHashes`] for the deploys in this block. pub(crate) approvals_hashes: Box, - /// The results from executing the deploys in the block. - pub(crate) execution_results: Vec, + /// The results from executing the transactions in the block. + pub(crate) execution_artifacts: Vec, /// The [`Effects`] and the upcoming validator sets determined by the `step` - pub(crate) maybe_step_effects_and_upcoming_era_validators: - Option, + pub(crate) step_outcome: Option, +} + +/// Type representing results of the speculative execution. +#[derive(Debug)] +pub enum SpeculativeExecutionResult { + InvalidTransaction(InvalidTransaction), + WasmV1(casper_binary_port::SpeculativeExecutionResult), } -#[derive(DataSize, Debug, Clone, Serialize)] -/// Wrapper for speculative execution prestate. -pub struct SpeculativeExecutionState { - /// State root on top of which to execute deploy. - pub state_root_hash: Digest, - /// Block time. - pub block_time: Timestamp, - /// Protocol version used when creating the original block. - pub protocol_version: ProtocolVersion, +impl SpeculativeExecutionResult { + pub fn invalid_gas_limit(transaction: Transaction) -> Self { + match transaction { + Transaction::Deploy(_) => SpeculativeExecutionResult::InvalidTransaction( + InvalidTransaction::Deploy(InvalidDeploy::UnableToCalculateGasLimit), + ), + Transaction::V1(_) => SpeculativeExecutionResult::InvalidTransaction( + InvalidTransaction::V1(InvalidTransactionV1::UnableToCalculateGasLimit), + ), + } + } } /// State to use to construct the next block in the blockchain. Includes the state root hash for the diff --git a/node/src/components/contract_runtime/utils.rs b/node/src/components/contract_runtime/utils.rs index 4d842e75a9..8675cb3ec5 100644 --- a/node/src/components/contract_runtime/utils.rs +++ b/node/src/components/contract_runtime/utils.rs @@ -1,26 +1,11 @@ use num_rational::Ratio; -use once_cell::sync::Lazy; -use std::{ - cmp, - collections::{BTreeMap, HashMap}, - ops::Range, - sync::{Arc, Mutex}, -}; -use tracing::{debug, error, info}; - -use casper_execution_engine::engine_state::ExecutionEngineV1; -use casper_storage::{ - data_access_layer::DataAccessLayer, global_state::state::lmdb::LmdbGlobalState, -}; -use casper_types::{Chainspec, EraId, Key}; use crate::{ contract_runtime::{ exec_queue::{ExecQueue, QueueItem}, execute_finalized_block, metrics::Metrics, - rewards, BlockAndExecutionResults, BlockExecutionError, ExecutionPreState, - StepEffectsAndUpcomingEraValidators, + rewards, BlockAndExecutionArtifacts, BlockExecutionError, ExecutionPreState, StepOutcome, }, effect::{ announcements::{ContractRuntimeAnnouncement, FatalAnnouncement, MetaBlockAnnouncement}, @@ -31,6 +16,22 @@ use crate::{ types::{ExecutableBlock, MetaBlock, MetaBlockState}, }; +use casper_binary_port::SpeculativeExecutionResult; +use casper_execution_engine::engine_state::{ExecutionEngineV1, WasmV1Result}; +use casper_storage::{ + data_access_layer::DataAccessLayer, global_state::state::lmdb::LmdbGlobalState, +}; +use casper_types::{Chainspec, EraId, Key}; +use once_cell::sync::Lazy; +use std::{ + cmp, + collections::{BTreeMap, HashMap}, + fmt::Debug, + ops::Range, + sync::{Arc, Mutex}, +}; +use tracing::{debug, error, info}; + /// Maximum number of resource intensive tasks that can be run in parallel. /// /// TODO: Fine tune this constant to the machine executing the node. @@ -47,13 +48,18 @@ static INTENSIVE_TASKS_SEMAPHORE: Lazy = pub(super) async fn run_intensive_task(task: T) -> V where T: 'static + Send + FnOnce() -> V, - V: 'static + Send, + V: 'static + Send + Debug, { // This will never panic since the semaphore is never closed. let _permit = INTENSIVE_TASKS_SEMAPHORE.acquire().await.unwrap(); - tokio::task::spawn_blocking(task) - .await - .expect("task panicked") + let result = tokio::task::spawn_blocking(task).await; + match result { + Ok(ret) => ret, + Err(err) => { + error!("{:?}", err); + panic!("intensive contract runtime task errored: {:?}", err); + } + } } #[allow(clippy::too_many_arguments)] @@ -80,8 +86,6 @@ pub(super) async fn exec_or_requeue( { debug!("ContractRuntime: execute_finalized_block_or_requeue"); let contract_runtime_metrics = metrics.clone(); - let block_max_install_upgrade_count = - chainspec.transaction_config.block_max_install_upgrade_count; let is_era_end = executable_block.era_report.is_some(); if is_era_end && executable_block.rewards.is_none() { executable_block.rewards = Some(if chainspec.core_config.compute_rewards { @@ -94,7 +98,7 @@ pub(super) async fn exec_or_requeue( { Ok(rewards) => rewards, Err(e) => { - return fatal!(effect_builder, "Failed to compute the rewards: {e:?}").await + return fatal!(effect_builder, "Failed to compute the rewards: {e:?}").await; } }; @@ -111,6 +115,8 @@ pub(super) async fn exec_or_requeue( let block_max_standard_count = chainspec.transaction_config.block_max_standard_count; let block_max_mint_count = chainspec.transaction_config.block_max_mint_count; let block_max_auction_count = chainspec.transaction_config.block_max_auction_count; + let block_max_install_upgrade_count = + chainspec.transaction_config.block_max_install_upgrade_count; let go_up = chainspec.vacancy_config.upper_threshold; let go_down = chainspec.vacancy_config.lower_threshold; let max = chainspec.vacancy_config.max_gas_price; @@ -119,10 +125,32 @@ pub(super) async fn exec_or_requeue( let era_id = executable_block.era_id; let block_height = executable_block.height; - let switch_block_transaction_hashes = executable_block.transactions.len() as u64; + let per_block_capacity = { + block_max_install_upgrade_count + + block_max_standard_count + + block_max_mint_count + + block_max_auction_count + } as u64; + + let switch_block_utilization_score = { + let has_hit_slot_limt = { + (executable_block.mint.len() as u32 >= block_max_mint_count) + || (executable_block.auction.len() as u32 >= block_max_auction_count) + || (executable_block.standard.len() as u32 >= block_max_standard_count) + || (executable_block.install_upgrade.len() as u32 + >= block_max_install_upgrade_count) + }; + + if has_hit_slot_limt { + 100u64 + } else { + let num = executable_block.transactions.len() as u64; + Ratio::new(num * 100, per_block_capacity).to_integer() + } + }; let maybe_utilization = effect_builder - .get_block_utilization(era_id, block_height, switch_block_transaction_hashes) + .get_block_utilization(era_id, block_height, switch_block_utilization_score) .await; match maybe_utilization { @@ -131,18 +159,7 @@ pub(super) async fn exec_or_requeue( return fatal!(effect_builder, "{}", error).await; } Some((utilization, block_count)) => { - let per_block_capacity = { - block_max_install_upgrade_count - + block_max_standard_count - + block_max_mint_count - + block_max_auction_count - } as u64; - - let era_score = { - let numerator = utilization * 100; - let denominator = per_block_capacity * block_count; - Ratio::new(numerator, denominator).to_integer() - }; + let era_score = { Ratio::new(utilization, block_count).to_integer() }; let new_gas_price = if era_score >= go_up { let new_gas_price = current_gas_price + 1; @@ -169,11 +186,11 @@ pub(super) async fn exec_or_requeue( None }; - let BlockAndExecutionResults { + let BlockAndExecutionArtifacts { block, approvals_hashes, - execution_results, - maybe_step_effects_and_upcoming_era_validators, + execution_artifacts, + step_outcome: maybe_step_outcome, } = match run_intensive_task(move || { debug!("ContractRuntime: execute_finalized_block"); execute_finalized_block( @@ -190,7 +207,7 @@ pub(super) async fn exec_or_requeue( }) .await { - Ok(block_and_execution_results) => block_and_execution_results, + Ok(ret) => ret, Err(error) => { error!(%error, "failed to execute block"); return fatal!(effect_builder, "{}", error).await; @@ -221,10 +238,10 @@ pub(super) async fn exec_or_requeue( let current_era_id = block.era_id(); - if let Some(StepEffectsAndUpcomingEraValidators { + if let Some(StepOutcome { step_effects, mut upcoming_era_validators, - }) = maybe_step_effects_and_upcoming_era_validators + }) = maybe_step_outcome { effect_builder .announce_commit_step_success(current_era_id, step_effects) @@ -257,29 +274,26 @@ pub(super) async fn exec_or_requeue( "executed block" ); - let execution_results_map: HashMap<_, _> = execution_results + let artifacts_map: HashMap<_, _> = execution_artifacts .iter() .cloned() .map(|artifact| (artifact.transaction_hash, artifact.execution_result)) .collect(); + if meta_block_state.register_as_stored().was_updated() { effect_builder - .put_executed_block_to_storage( - Arc::clone(&block), - approvals_hashes, - execution_results_map, - ) + .put_executed_block_to_storage(Arc::clone(&block), approvals_hashes, artifacts_map) .await; } else { effect_builder .put_approvals_hashes_to_storage(approvals_hashes) .await; effect_builder - .put_execution_results_to_storage( + .put_execution_artifacts_to_storage( *block.hash(), block.height(), block.era_id(), - execution_results_map, + artifacts_map, ) .await; } @@ -295,7 +309,7 @@ pub(super) async fn exec_or_requeue( ); } - let meta_block = MetaBlock::new_forward(block, execution_results, meta_block_state); + let meta_block = MetaBlock::new_forward(block, execution_artifacts, meta_block_state); effect_builder.announce_meta_block(meta_block).await; // If the child is already finalized, start execution. @@ -371,15 +385,31 @@ pub(super) fn calculate_prune_eras( Some(range.map(EraId::new).map(Key::EraInfo).collect()) } +pub(crate) fn spec_exec_from_wasm_v1_result( + wasm_v1_result: WasmV1Result, +) -> SpeculativeExecutionResult { + let transfers = wasm_v1_result.transfers().to_owned(); + let limit = wasm_v1_result.limit().to_owned(); + let consumed = wasm_v1_result.consumed().to_owned(); + let effects = wasm_v1_result.effects().to_owned(); + let messages = wasm_v1_result.messages().to_owned(); + let error_msg = wasm_v1_result + .error() + .to_owned() + .map(|err| format!("{:?}", err)); + + SpeculativeExecutionResult::new(transfers, limit, consumed, effects, messages, error_msg) +} + #[cfg(test)] mod tests { use super::*; #[test] fn calculation_is_safe_with_invalid_input() { - assert_eq!(calculate_prune_eras(EraId::new(0), 0, 0, 0,), None); - assert_eq!(calculate_prune_eras(EraId::new(0), 0, 0, 5,), None); - assert_eq!(calculate_prune_eras(EraId::new(u64::MAX), 0, 0, 0,), None); + assert_eq!(calculate_prune_eras(EraId::new(0), 0, 0, 0), None); + assert_eq!(calculate_prune_eras(EraId::new(0), 0, 0, 5), None); + assert_eq!(calculate_prune_eras(EraId::new(u64::MAX), 0, 0, 0), None); assert_eq!( calculate_prune_eras(EraId::new(u64::MAX), 1, u64::MAX, u64::MAX), None @@ -392,7 +422,7 @@ mod tests { // batch out of u64::MAX of erainfos needs to iterate over all chunks. assert!(calculate_prune_eras(EraId::new(u64::MAX), 0, u64::MAX, 100,).is_none(),); assert_eq!( - calculate_prune_eras(EraId::new(u64::MAX), 1, 100, 100,) + calculate_prune_eras(EraId::new(u64::MAX), 1, 100, 100) .unwrap() .len(), 100 @@ -412,7 +442,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 1 + 1, ), Some(vec![Key::EraInfo(EraId::new(0))]) ); @@ -421,7 +451,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 1, - 1 + 1, ), Some(vec![Key::EraInfo(EraId::new(1))]) ); @@ -430,7 +460,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 1 + 1, ), Some(vec![Key::EraInfo(EraId::new(2))]) ); @@ -439,7 +469,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 3, - 1 + 1, ), Some(vec![Key::EraInfo(EraId::new(3))]) ); @@ -448,7 +478,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 4, - 1 + 1, ), Some(vec![Key::EraInfo(EraId::new(4))]) ); @@ -473,11 +503,11 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 2 + 2, ), Some(vec![ Key::EraInfo(EraId::new(0)), - Key::EraInfo(EraId::new(1)) + Key::EraInfo(EraId::new(1)), ]) ); assert_eq!( @@ -485,11 +515,11 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 1, - 2 + 2, ), Some(vec![ Key::EraInfo(EraId::new(2)), - Key::EraInfo(EraId::new(3)) + Key::EraInfo(EraId::new(3)), ]) ); assert_eq!( @@ -497,7 +527,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 2 + 2, ), Some(vec![Key::EraInfo(EraId::new(4))]) ); @@ -506,7 +536,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 3, - 2 + 2, ), None ); @@ -522,7 +552,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 3 + 3, ), Some(vec![ Key::EraInfo(EraId::new(0)), @@ -535,7 +565,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 1, - 3 + 3, ), Some(vec![ Key::EraInfo(EraId::new(3)), @@ -548,7 +578,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 3 + 3, ), None ); @@ -564,7 +594,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 4 + 4, ), Some(vec![ Key::EraInfo(EraId::new(0)), @@ -578,9 +608,9 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 1, - 4 + 4, ), - Some(vec![Key::EraInfo(EraId::new(4)),]) + Some(vec![Key::EraInfo(EraId::new(4))]) ); assert_eq!( @@ -588,7 +618,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 4 + 4, ), None ); @@ -604,7 +634,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 5 + 5, ), Some(vec![ Key::EraInfo(EraId::new(0)), @@ -629,7 +659,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 5 + 5, ), None ); @@ -645,7 +675,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height, - 6 + 6, ), Some(vec![ Key::EraInfo(EraId::new(0)), @@ -670,7 +700,7 @@ mod tests { ACTIVATION_POINT_ERA_ID, activation_height, current_height + 2, - 6 + 6, ), None ); diff --git a/node/src/components/event_stream_server/sse_server.rs b/node/src/components/event_stream_server/sse_server.rs index 614f099f21..02351b99bb 100644 --- a/node/src/components/event_stream_server/sse_server.rs +++ b/node/src/components/event_stream_server/sse_server.rs @@ -177,10 +177,7 @@ impl SseData { /// Returns a random `SseData::Step`. pub(super) fn random_step(rng: &mut TestRng) -> Self { - let execution_effects = match ExecutionResultV2::random(rng) { - ExecutionResultV2::Success { effects, .. } - | ExecutionResultV2::Failure { effects, .. } => effects, - }; + let execution_effects = ExecutionResultV2::random(rng).effects; SseData::Step { era_id: EraId::new(rng.gen()), execution_effects, diff --git a/node/src/components/event_stream_server/tests.rs b/node/src/components/event_stream_server/tests.rs index b4d468ef5f..4073a49bcb 100644 --- a/node/src/components/event_stream_server/tests.rs +++ b/node/src/components/event_stream_server/tests.rs @@ -1071,8 +1071,6 @@ fn json_schema_check() { "{}/../resources/test/sse_data_schema.json", env!("CARGO_MANIFEST_DIR") ); - assert_schema( - schema_path, - serde_json::to_string_pretty(&schema_for!(SseData)).unwrap(), - ); + let pretty = serde_json::to_string_pretty(&schema_for!(SseData)).unwrap(); + assert_schema(schema_path, pretty); } diff --git a/node/src/components/fetcher.rs b/node/src/components/fetcher.rs index 07b1bd351f..4f84f78273 100644 --- a/node/src/components/fetcher.rs +++ b/node/src/components/fetcher.rs @@ -134,7 +134,7 @@ where Source::PeerGossiped(peer) | Source::Peer(peer) => { self.got_from_peer(effect_builder, peer, item) } - Source::Client | Source::SpeculativeExec(_) | Source::Ourself => Effects::new(), + Source::Client | Source::SpeculativeExec | Source::Ourself => Effects::new(), }, Event::GotInvalidRemotely { .. } => Effects::new(), Event::AbsentRemotely { id, peer } => { diff --git a/node/src/components/fetcher/fetcher_impls/transaction_fetcher.rs b/node/src/components/fetcher/fetcher_impls/transaction_fetcher.rs index 7f64ef5a2c..2b1bdc8e91 100644 --- a/node/src/components/fetcher/fetcher_impls/transaction_fetcher.rs +++ b/node/src/components/fetcher/fetcher_impls/transaction_fetcher.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, time::Duration}; use async_trait::async_trait; use futures::FutureExt; -use casper_types::{Transaction, TransactionConfigFailure, TransactionId}; +use casper_types::{InvalidTransaction, Transaction, TransactionId}; use crate::{ components::fetcher::{ @@ -16,7 +16,7 @@ use crate::{ impl FetchItem for Transaction { type Id = TransactionId; - type ValidationError = TransactionConfigFailure; + type ValidationError = InvalidTransaction; type ValidationMetadata = EmptyValidationMetadata; const TAG: Tag = Tag::Transaction; diff --git a/node/src/components/fetcher/tests.rs b/node/src/components/fetcher/tests.rs index 4d15e6f258..fcea95e531 100644 --- a/node/src/components/fetcher/tests.rs +++ b/node/src/components/fetcher/tests.rs @@ -13,7 +13,7 @@ use thiserror::Error; use casper_types::{ testing::TestRng, BlockV2, Chainspec, ChainspecRawBytes, FinalitySignatureV2, Transaction, - TransactionHash, TransactionId, + TransactionConfig, TransactionHash, TransactionId, }; use super::*; @@ -223,10 +223,10 @@ impl ReactorTrait for Reactor { } Event::AcceptTransactionRequest(AcceptTransactionRequest { transaction, - speculative_exec_at_block, + is_speculative, responder, }) => { - assert!(speculative_exec_at_block.is_none()); + assert!(!is_speculative); let event = transaction_acceptor::Event::Accept { transaction, source: Source::Client, @@ -295,6 +295,7 @@ impl ReactorTrait for Reactor { chainspec.core_config.unbonding_delay, Some(registry), false, + TransactionConfig::default(), ) .unwrap(); @@ -382,7 +383,9 @@ impl NetworkedReactor for Reactor { fn announce_transaction_received( txn: Transaction, ) -> impl FnOnce(EffectBuilder) -> Effects { - |effect_builder: EffectBuilder| effect_builder.try_accept_transaction(txn, None).ignore() + |effect_builder: EffectBuilder| { + effect_builder.try_accept_transaction(txn, false).ignore() + } } type FetchedTransactionResult = Arc>)>>; diff --git a/node/src/components/gossiper/tests.rs b/node/src/components/gossiper/tests.rs index ef9d98796b..78c657bbe6 100644 --- a/node/src/components/gossiper/tests.rs +++ b/node/src/components/gossiper/tests.rs @@ -19,7 +19,7 @@ use tracing::debug; use casper_types::{ testing::TestRng, BlockV2, Chainspec, ChainspecRawBytes, EraId, FinalitySignatureV2, - ProtocolVersion, TimeDiff, Transaction, + ProtocolVersion, TimeDiff, Transaction, TransactionConfig, }; use super::*; @@ -169,6 +169,7 @@ impl reactor::Reactor for Reactor { RECENT_ERA_COUNT, Some(registry), false, + TransactionConfig::default(), ) .unwrap(); @@ -266,10 +267,10 @@ impl reactor::Reactor for Reactor { ), Event::AcceptTransactionRequest(AcceptTransactionRequest { transaction, - speculative_exec_at_block, + is_speculative, responder, }) => { - assert!(speculative_exec_at_block.is_none()); + assert!(!is_speculative); let event = transaction_acceptor::Event::Accept { transaction, source: Source::Client, @@ -335,7 +336,9 @@ fn announce_transaction_received( transaction: &Transaction, ) -> impl FnOnce(EffectBuilder) -> Effects { let txn = transaction.clone(); - |effect_builder: EffectBuilder| effect_builder.try_accept_transaction(txn, None).ignore() + |effect_builder: EffectBuilder| { + effect_builder.try_accept_transaction(txn, false).ignore() + } } async fn run_gossip(rng: &mut TestRng, network_size: usize, txn_count: usize) { diff --git a/node/src/components/rest_server/info.rs b/node/src/components/rest_server/info.rs index cbabc8a261..8b0bb2ddef 100644 --- a/node/src/components/rest_server/info.rs +++ b/node/src/components/rest_server/info.rs @@ -3,10 +3,9 @@ use std::str; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use casper_types::{ - binary_port::ConsensusValidatorChanges, ChainspecRawBytes, EraId, ProtocolVersion, PublicKey, - ValidatorChange, -}; +use casper_binary_port::ConsensusValidatorChanges; + +use casper_types::{ChainspecRawBytes, EraId, ProtocolVersion, PublicKey, ValidatorChange}; /// A single change to a validator's status in the given era. #[derive(PartialEq, Eq, Serialize, Deserialize, Debug, JsonSchema)] diff --git a/node/src/components/storage.rs b/node/src/components/storage.rs index eca896456d..1f480ee6b1 100644 --- a/node/src/components/storage.rs +++ b/node/src/components/storage.rs @@ -38,6 +38,7 @@ mod metrics; mod object_pool; #[cfg(test)] mod tests; +mod utils; use casper_storage::block_store::{ lmdb::{IndexedLmdbBlockStore, LmdbBlockStore}, @@ -59,18 +60,16 @@ use std::{ sync::Arc, }; +use casper_storage::DbRawBytesSpec; #[cfg(test)] use casper_types::SignedBlock; use casper_types::{ - binary_port::DbRawBytesSpec, bytesrepr::{FromBytes, ToBytes}, - execution::{ - execution_result_v1, ExecutionResult, ExecutionResultV1, ExecutionResultV2, TransformKindV2, - }, + execution::{execution_result_v1, ExecutionResult, ExecutionResultV1, ExecutionResultV2}, Approval, ApprovalsHash, AvailableBlockRange, Block, BlockBody, BlockHash, BlockHeader, BlockSignatures, BlockSignaturesV1, BlockSignaturesV2, BlockV2, ChainNameDigest, DeployHash, - EraId, ExecutionInfo, FinalitySignature, ProtocolVersion, SignedBlockHeader, StoredValue, - Timestamp, Transaction, TransactionHash, TransactionHeader, TransactionId, Transfer, + EraId, ExecutionInfo, FinalitySignature, ProtocolVersion, SignedBlockHeader, Timestamp, + Transaction, TransactionConfig, TransactionHash, TransactionHeader, TransactionId, Transfer, }; use datasize::DataSize; use prometheus::Registry; @@ -149,6 +148,8 @@ pub struct Storage { max_ttl: MaxTtl, /// The hash of the chain name. chain_name_hash: ChainNameDigest, + /// The transaction config as specified by the chainspec. + transaction_config: TransactionConfig, /// The utilization of blocks. utilization_tracker: BTreeMap>, } @@ -246,6 +247,7 @@ impl Storage { recent_era_count: u64, registry: Option<&Registry>, force_resync: bool, + transaction_config: TransactionConfig, ) -> Result { let config = cfg.value(); @@ -290,6 +292,7 @@ impl Storage { utilization_tracker: BTreeMap::new(), metrics, chain_name_hash: ChainNameDigest::from_chain_name(network_name), + transaction_config, }; if force_resync { @@ -948,9 +951,12 @@ impl Storage { ref transaction_hash, ref finalized_approvals, responder, - } => responder - .respond(self.store_finalized_approvals(transaction_hash, finalized_approvals)?) - .ignore(), + } => { + info!(txt=?transaction_hash, count=finalized_approvals.len(), "storing finalized approvals {:?}", finalized_approvals); + responder + .respond(self.store_finalized_approvals(transaction_hash, finalized_approvals)?) + .ignore() + } StorageRequest::PutExecutedBlock { block, approvals_hashes, @@ -958,8 +964,10 @@ impl Storage { responder, } => { let block: Block = (*block).clone().into(); + let transaction_config = self.transaction_config; responder .respond(self.put_executed_block( + transaction_config, &block, &approvals_hashes, execution_results, @@ -986,18 +994,26 @@ impl Storage { responder, record_id, } => { + let db_table_id = utils::db_table_id_from_record_id(record_id) + .map_err(|_| FatalStorageError::UnexpectedRecordId(record_id))?; let txn = self.block_store.checkout_ro()?; - let maybe_data: Option = txn.read((record_id, key))?; - responder.respond(maybe_data).ignore() + let maybe_data: Option = txn.read((db_table_id, key))?; + match maybe_data { + None => responder.respond(None).ignore(), + Some(db_raw) => responder.respond(Some(db_raw)).ignore(), + } } StorageRequest::GetBlockUtilizationScore { era_id, block_height, - transaction_count, + switch_block_utilization, responder, } => { - let utilization = - self.get_block_utilization_score(era_id, block_height, transaction_count); + let utilization = self.get_block_utilization_score( + era_id, + block_height, + switch_block_utilization, + ); responder.respond(utilization).ignore() } @@ -1044,13 +1060,14 @@ impl Storage { pub(crate) fn put_executed_block( &mut self, + transaction_config: TransactionConfig, block: &Block, approvals_hashes: &ApprovalsHashes, execution_results: HashMap, ) -> Result { let mut txn = self.block_store.checkout_rw()?; - let transaction_hash_count = block.transaction_count(); let era_id = block.era_id(); + let block_utilization_score = block.block_utilization(transaction_config); let block_hash = txn.write(block)?; let _ = txn.write(approvals_hashes)?; let block_info = BlockHashHeightAndEra::new(block_hash, block.height(), block.era_id()); @@ -1061,17 +1078,13 @@ impl Storage { })?; txn.commit()?; - if let Some(block_score) = self.utilization_tracker.get_mut(&era_id) { - block_score.insert(block.height(), transaction_hash_count); - }; - match self.utilization_tracker.get_mut(&era_id) { Some(block_score) => { - block_score.insert(block.height(), transaction_hash_count); + block_score.insert(block.height(), block_utilization_score); } None => { let mut block_score = BTreeMap::new(); - block_score.insert(block.height(), transaction_hash_count); + block_score.insert(block.height(), block_utilization_score); self.utilization_tracker.insert(era_id, block_score); } } @@ -1960,11 +1973,11 @@ impl Storage { &mut self, era_id: EraId, block_height: u64, - transaction_count: u64, + block_utilization: u64, ) -> Option<(u64, u64)> { let ret = match self.utilization_tracker.get_mut(&era_id) { Some(utilization) => { - utilization.entry(block_height).or_insert(transaction_count); + utilization.entry(block_height).or_insert(block_utilization); let transaction_count = utilization.values().into_iter().sum(); let block_count = utilization.keys().len() as u64; @@ -1973,12 +1986,12 @@ impl Storage { } None => { let mut utilization = BTreeMap::new(); - utilization.insert(block_height, transaction_count); + utilization.insert(block_height, block_utilization); self.utilization_tracker.insert(era_id, utilization); let block_count = 1u64; - Some((transaction_count, block_count)) + Some((block_utilization, block_count)) } }; @@ -2059,30 +2072,34 @@ fn move_storage_files_to_network_subdir( /// Returns all `Transform::WriteTransfer`s from the execution effects if this is an /// `ExecutionResult::Success`, or an empty `Vec` if `ExecutionResult::Failure`. fn successful_transfers(execution_result: &ExecutionResult) -> Vec { - let mut transfers: Vec = vec![]; + let mut all_transfers: Vec = vec![]; match execution_result { ExecutionResult::V1(ExecutionResultV1::Success { effect, .. }) => { - for transform_entry in &effect.transforms { - if let execution_result_v1::TransformKindV1::WriteTransfer(transfer) = - &transform_entry.transform + for transform_v1 in &effect.transforms { + if let execution_result_v1::TransformKindV1::WriteTransfer(transfer_v1) = + &transform_v1.transform { - transfers.push(*transfer); + all_transfers.push(Transfer::V1(transfer_v1.clone())); } } } - ExecutionResult::V2(ExecutionResultV2::Success { effects, .. }) => { - for transform in effects.transforms() { - if let TransformKindV2::Write(StoredValue::Transfer(transfer)) = transform.kind() { - transfers.push(*transfer); + ExecutionResult::V2(ExecutionResultV2 { + transfers, + error_message, + .. + }) => { + if error_message.is_none() { + for transfer in transfers { + all_transfers.push(transfer.clone()); } } + // else no-op: we only record transfers from successful executions. } - ExecutionResult::V1(ExecutionResultV1::Failure { .. }) - | ExecutionResult::V2(ExecutionResultV2::Failure { .. }) => { + ExecutionResult::V1(ExecutionResultV1::Failure { .. }) => { // No-op: we only record transfers from successful executions. } } - transfers + all_transfers } // Testing code. The functions below allow direct inspection of the storage component and should diff --git a/node/src/components/storage/error.rs b/node/src/components/storage/error.rs index f5c609bdd1..7a7531d4d0 100644 --- a/node/src/components/storage/error.rs +++ b/node/src/components/storage/error.rs @@ -1,12 +1,12 @@ use std::{fmt::Debug, io, path::PathBuf}; +use casper_binary_port::RecordId; use thiserror::Error; use tracing::error; use casper_types::{ - binary_port::RecordId, bytesrepr, crypto, BlockBody, BlockHash, BlockHeader, - BlockValidationError, DeployHash, Digest, EraId, FinalitySignature, FinalitySignatureId, - TransactionHash, + bytesrepr, crypto, BlockBody, BlockHash, BlockHeader, BlockValidationError, DeployHash, Digest, + EraId, FinalitySignature, FinalitySignatureId, TransactionHash, }; use crate::types::VariantMismatch; @@ -180,6 +180,9 @@ pub enum FatalStorageError { /// BlockStoreError #[error(transparent)] BlockStoreError(#[from] BlockStoreError), + /// BlockStoreError + #[error("unexpected record id {0}")] + UnexpectedRecordId(RecordId), } impl From> for FatalStorageError { diff --git a/node/src/components/storage/tests.rs b/node/src/components/storage/tests.rs index c7e1ec6b9d..e45cec5c4a 100644 --- a/node/src/components/storage/tests.rs +++ b/node/src/components/storage/tests.rs @@ -20,17 +20,15 @@ use casper_storage::block_store::{ BlockStoreProvider, BlockStoreTransaction, DataReader, DataWriter, }; use casper_types::{ - execution::{ - execution_result_v1::{ExecutionEffect, ExecutionResultV1, TransformKindV1, TransformV1}, - ExecutionResult, ExecutionResultV2, - }, + execution::{Effects, ExecutionResult, ExecutionResultV2}, generate_ed25519_keypair, testing::TestRng, ApprovalsHash, AvailableBlockRange, Block, BlockHash, BlockHeader, BlockSignatures, BlockSignaturesV2, BlockV2, ChainNameDigest, Chainspec, ChainspecRawBytes, Deploy, DeployHash, - Digest, EraId, ExecutionInfo, FinalitySignature, FinalitySignatureV2, Key, ProtocolVersion, - PublicKey, SecretKey, SignedBlockHeader, TestBlockBuilder, TestBlockV1Builder, TimeDiff, - Transaction, TransactionHash, TransactionV1Hash, Transfer, U512, + Digest, EraId, ExecutionInfo, FinalitySignature, FinalitySignatureV2, Gas, InitiatorAddr, + ProtocolVersion, PublicKey, SecretKey, SignedBlockHeader, TestBlockBuilder, TestBlockV1Builder, + TimeDiff, Transaction, TransactionConfig, TransactionHash, TransactionV1Hash, Transfer, + TransferV2, U512, }; use tempfile::tempdir; @@ -196,6 +194,7 @@ fn storage_fixture(harness: &ComponentHarness) -> Storage { RECENT_ERA_COUNT, None, false, + TransactionConfig::default(), ) .expect("could not create storage component fixture") } @@ -226,6 +225,7 @@ fn storage_fixture_from_parts( recent_era_count.unwrap_or(RECENT_ERA_COUNT), None, false, + TransactionConfig::default(), ) .expect("could not create storage component fixture from parts") } @@ -248,6 +248,7 @@ fn storage_fixture_with_force_resync(cfg: &WithDir) -> Storage { RECENT_ERA_COUNT, None, true, + TransactionConfig::default(), ) .expect("could not create storage component fixture") } @@ -1353,30 +1354,29 @@ fn store_execution_results_twice_for_same_block_deploy_pair() { fn prepare_exec_result_with_transfer( rng: &mut TestRng, - deploy_hash: &DeployHash, + txn_hash: &TransactionHash, ) -> (ExecutionResult, Transfer) { - let transfer = Transfer::new( - *deploy_hash, - rng.gen(), + let initiator_addr = InitiatorAddr::random(rng); + let transfer = Transfer::V2(TransferV2::new( + *txn_hash, + initiator_addr.clone(), Some(rng.gen()), rng.gen(), rng.gen(), rng.gen(), - rng.gen(), + Gas::from(rng.gen::()), Some(rng.gen()), - ); - let transform = TransformV1 { - key: Key::DeployInfo(*deploy_hash).to_formatted_string(), - transform: TransformKindV1::WriteTransfer(transfer), - }; - let effect = ExecutionEffect { - operations: vec![], - transforms: vec![transform], - }; - let exec_result = ExecutionResult::V1(ExecutionResultV1::Success { - effect, - transfers: vec![], - cost: rng.gen(), + )); + let limit = Gas::new(rng.gen::()); + let exec_result = ExecutionResult::V2(ExecutionResultV2 { + initiator: initiator_addr, + error_message: None, + limit, + cost: limit.value(), + consumed: limit, + payment: vec![], + transfers: vec![transfer.clone()], + effects: Effects::new(), }); (exec_result, transfer) } @@ -1398,7 +1398,8 @@ fn store_identical_execution_results() { put_block(&mut harness, &mut storage, block.clone()); let block_hash = *block.hash(); - let (exec_result, transfer) = prepare_exec_result_with_transfer(&mut harness.rng, &deploy_hash); + let (exec_result, transfer) = + prepare_exec_result_with_transfer(&mut harness.rng, &TransactionHash::Deploy(deploy_hash)); let mut exec_results = HashMap::new(); exec_results.insert(TransactionHash::from(deploy_hash), exec_result.clone()); @@ -1495,7 +1496,8 @@ fn should_provide_transfers_after_emptied() { let block_hash = *block.hash(); put_block(&mut harness, &mut storage, Arc::new(block.clone())); - let (exec_result, transfer) = prepare_exec_result_with_transfer(&mut harness.rng, &deploy_hash); + let (exec_result, transfer) = + prepare_exec_result_with_transfer(&mut harness.rng, &TransactionHash::Deploy(deploy_hash)); let mut exec_results = HashMap::new(); exec_results.insert(TransactionHash::from(deploy_hash), exec_result); @@ -1784,6 +1786,7 @@ fn should_create_subdir_named_after_network() { RECENT_ERA_COUNT, None, false, + TransactionConfig::default(), ) .unwrap(); @@ -2843,6 +2846,7 @@ fn assert_highest_block_in_storage( // Since this change impacts the storage APIs, create a test to prove that we can still access old // unversioned blocks through the new APIs and also check that both versioned and unversioned blocks // can co-exist in storage. +#[ignore = "stop ignoring once decision around Transfer type is made"] fn check_block_operations_with_node_1_5_2_storage() { let rng: TestRng = TestRng::new(); @@ -2899,7 +2903,10 @@ fn check_block_operations_with_node_1_5_2_storage() { let mut stored_transfers: Vec = transfers .unwrap() .iter() - .map(|transfer| transfer.deploy_hash) + .map(|transfer| match transfer { + Transfer::V1(transfer_v1) => transfer_v1.deploy_hash, + _ => panic!("expected transfer v1 variant"), + }) .collect(); stored_transfers.sort(); let mut expected_deploys = block_info.deploy_hashes.clone(); diff --git a/node/src/components/storage/utils.rs b/node/src/components/storage/utils.rs new file mode 100644 index 0000000000..0c16f942b7 --- /dev/null +++ b/node/src/components/storage/utils.rs @@ -0,0 +1,9 @@ +use casper_binary_port::RecordId; +use casper_storage::{DbTableId, UnknownDbTableId}; +use std::convert::TryFrom; + +pub(crate) fn db_table_id_from_record_id( + record_id: RecordId, +) -> Result { + DbTableId::try_from(record_id as u16) +} diff --git a/node/src/components/transaction_acceptor.rs b/node/src/components/transaction_acceptor.rs index 4bbf972d6f..d95f145f8b 100644 --- a/node/src/components/transaction_acceptor.rs +++ b/node/src/components/transaction_acceptor.rs @@ -4,21 +4,21 @@ mod event; mod metrics; mod tests; -use std::{collections::BTreeSet, fmt::Debug, sync::Arc}; +use std::{collections::BTreeSet, fmt::Debug, sync::Arc, time::SystemTime}; use datasize::DataSize; use prometheus::Registry; use tracing::{debug, error, trace}; use casper_execution_engine::engine_state::MAX_PAYMENT; -use casper_storage::data_access_layer::BalanceRequest; +use casper_storage::data_access_layer::{balance::BalanceHandling, BalanceRequest}; use casper_types::{ account::AccountHash, addressable_entity::AddressableEntity, contracts::ContractHash, - package::Package, system::auction::ARG_AMOUNT, AddressableEntityHash, - AddressableEntityIdentifier, BlockHeader, Chainspec, EntityAddr, EntityVersion, - EntityVersionKey, ExecutableDeployItem, ExecutableDeployItemIdentifier, InitiatorAddr, Key, - PackageAddr, PackageHash, PackageIdentifier, ProtocolVersion, SystemConfig, Transaction, - TransactionConfig, TransactionEntryPoint, TransactionInvocationTarget, TransactionTarget, U512, + system::auction::ARG_AMOUNT, AddressableEntityHash, AddressableEntityIdentifier, BlockHeader, + Chainspec, EntityAddr, EntityVersion, EntityVersionKey, ExecutableDeployItem, + ExecutableDeployItemIdentifier, HoldsEpoch, InitiatorAddr, Key, Package, PackageAddr, + PackageHash, PackageIdentifier, Transaction, TransactionEntryPoint, + TransactionInvocationTarget, TransactionTarget, U512, }; use crate::{ @@ -72,20 +72,17 @@ impl ReactorEventT for REv where #[derive(Debug, DataSize)] pub struct TransactionAcceptor { acceptor_config: Config, - chain_name: String, - protocol_version: ProtocolVersion, - cost_table: SystemConfig, - transaction_config: TransactionConfig, - max_associated_keys: u32, + chainspec: Arc, administrators: BTreeSet, #[data_size(skip)] metrics: metrics::Metrics, + balance_hold_interval: u64, } impl TransactionAcceptor { pub(crate) fn new( acceptor_config: Config, - chainspec: &Chainspec, + chainspec: Arc, registry: &Registry, ) -> Result { let administrators = chainspec @@ -94,15 +91,13 @@ impl TransactionAcceptor { .iter() .map(|public_key| public_key.to_account_hash()) .collect(); + let balance_hold_interval = chainspec.core_config.balance_hold_interval.millis(); Ok(TransactionAcceptor { acceptor_config, - chain_name: chainspec.network_config.name.clone(), - protocol_version: chainspec.protocol_version(), - cost_table: chainspec.system_costs_config, - transaction_config: chainspec.transaction_config, - max_associated_keys: chainspec.core_config.max_associated_keys, + chainspec, administrators, metrics: metrics::Metrics::new(registry)?, + balance_hold_interval, }) } @@ -120,24 +115,18 @@ impl TransactionAcceptor { let is_config_compliant = match &event_metadata.transaction { Transaction::Deploy(deploy) => deploy .is_config_compliant( - &self.chain_name, - &self.cost_table, - &self.transaction_config, - self.max_associated_keys, + &self.chainspec, self.acceptor_config.timestamp_leeway, event_metadata.verification_start_timestamp, ) - .map_err(Error::from), + .map_err(|err| Error::InvalidTransaction(err.into())), Transaction::V1(txn) => txn .is_config_compliant( - &self.chain_name, - &self.cost_table, - &self.transaction_config, - self.max_associated_keys, + &self.chainspec, self.acceptor_config.timestamp_leeway, event_metadata.verification_start_timestamp, ) - .map_err(Error::from), + .map_err(|err| Error::InvalidTransaction(err.into())), }; if let Err(error) = is_config_compliant { @@ -160,23 +149,6 @@ impl TransactionAcceptor { ); } - // If this has been received from the speculative exec server, use the block specified in - // the request, otherwise use the highest complete block. - if let Source::SpeculativeExec(block_header) = &event_metadata.source { - let account_key = match event_metadata.transaction.initiator_addr() { - InitiatorAddr::PublicKey(public_key) => Key::from(public_key.to_account_hash()), - InitiatorAddr::AccountHash(account_hash) => Key::from(account_hash), - }; - let block_header = block_header.clone(); - return effect_builder - .get_addressable_entity(*block_header.state_root_hash(), account_key) - .event(move |result| Event::GetAddressableEntityResult { - event_metadata, - maybe_entity: result.into_option(), - block_header, - }); - } - effect_builder .get_highest_complete_block_header_from_storage() .event(move |maybe_block_header| Event::GetBlockHeaderResult { @@ -245,10 +217,15 @@ impl TransactionAcceptor { return self.reject_transaction(effect_builder, *event_metadata, error); } let protocol_version = block_header.protocol_version(); + let hold_interval = self.balance_hold_interval; + let block_time = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_millis() as u64; + let holds_epoch = HoldsEpoch::from_millis(block_time, hold_interval); + let balance_handling = BalanceHandling::Available { holds_epoch }; let balance_request = BalanceRequest::from_purse( *block_header.state_root_hash(), protocol_version, entity.main_purse(), + balance_handling, ); effect_builder .get_balance(balance_request) @@ -345,6 +322,18 @@ impl TransactionAcceptor { maybe_entity: result.into_option(), }) } + ExecutableDeployItemIdentifier::AddressableEntity( + AddressableEntityIdentifier::Addr(entity_addr), + ) => { + let query_key = Key::AddressableEntity(entity_addr); + effect_builder + .get_addressable_entity(*block_header.state_root_hash(), query_key) + .event(move |result| Event::GetAddressableEntityResult { + event_metadata, + block_header, + maybe_entity: result.into_option(), + }) + } ExecutableDeployItemIdentifier::Package( ref contract_package_identifier @ PackageIdentifier::Hash { package_hash, .. }, ) => { @@ -452,6 +441,18 @@ impl TransactionAcceptor { maybe_entity: result.into_option(), }) } + ExecutableDeployItemIdentifier::AddressableEntity( + AddressableEntityIdentifier::Addr(entity_addr), + ) => { + let key = Key::AddressableEntity(entity_addr); + effect_builder + .get_addressable_entity(*block_header.state_root_hash(), key) + .event(move |result| Event::GetAddressableEntityResult { + event_metadata, + block_header, + maybe_entity: result.into_option(), + }) + } ExecutableDeployItemIdentifier::Package( ref package_identifier @ PackageIdentifier::Hash { package_hash, .. }, ) => { @@ -497,14 +498,14 @@ impl TransactionAcceptor { } Transaction::V1(txn) => match txn.target() { TransactionTarget::Stored { id, .. } => match id { - TransactionInvocationTarget::InvocableEntity(entity_addr) => { + TransactionInvocationTarget::ByHash(entity_addr) => { NextStep::GetContract(EntityAddr::SmartContract(*entity_addr)) } - TransactionInvocationTarget::Package { addr, version } => { + TransactionInvocationTarget::ByPackageHash { addr, version } => { NextStep::GetPackage(*addr, *version) } - TransactionInvocationTarget::InvocableEntityAlias(_) - | TransactionInvocationTarget::PackageAlias { .. } => { + TransactionInvocationTarget::ByName(_) + | TransactionInvocationTarget::ByPackageName { .. } => { NextStep::CryptoValidation } }, @@ -639,8 +640,10 @@ impl TransactionAcceptor { } }; - let entity_version_key = - EntityVersionKey::new(self.protocol_version.value().major, entity_version); + let entity_version_key = EntityVersionKey::new( + self.chainspec.protocol_config.version.value().major, + entity_version, + ); if package.is_version_missing(entity_version_key) { let error = Error::parameter_failure( @@ -687,8 +690,12 @@ impl TransactionAcceptor { event_metadata: Box, ) -> Effects { let is_valid = match &event_metadata.transaction { - Transaction::Deploy(deploy) => deploy.is_valid().map_err(Error::from), - Transaction::V1(txn) => txn.verify().map_err(Error::from), + Transaction::Deploy(deploy) => deploy + .is_valid() + .map_err(|err| Error::InvalidTransaction(err.into())), + Transaction::V1(txn) => txn + .verify() + .map_err(|err| Error::InvalidTransaction(err.into())), }; if let Err(error) = is_valid { return self.reject_transaction(effect_builder, *event_metadata, error); @@ -696,7 +703,7 @@ impl TransactionAcceptor { // If this has been received from the speculative exec server, we just want to call the // responder and finish. Otherwise store the transaction and announce it if required. - if let Source::SpeculativeExec(_) = event_metadata.source { + if let Source::SpeculativeExec = event_metadata.source { if let Some(responder) = event_metadata.maybe_responder { return responder.respond(Ok(())).ignore(); } @@ -725,9 +732,7 @@ impl TransactionAcceptor { maybe_responder, verification_start_timestamp, } = event_metadata; - if !matches!(source, Source::SpeculativeExec(_)) { - self.metrics.observe_rejected(verification_start_timestamp); - } + self.metrics.observe_rejected(verification_start_timestamp); let mut effects = Effects::new(); if let Some(responder) = maybe_responder { // The client has submitted an invalid transaction @@ -735,14 +740,11 @@ impl TransactionAcceptor { effects.extend(responder.respond(Err(error)).ignore()); } - // If this has NOT been received from the speculative exec server, announce it. - if !matches!(source, Source::SpeculativeExec(_)) { - effects.extend( - effect_builder - .announce_invalid_transaction(transaction, source) - .ignore(), - ); - } + effects.extend( + effect_builder + .announce_invalid_transaction(transaction, source) + .ignore(), + ); effects } @@ -823,6 +825,10 @@ impl TransactionAcceptor { impl Component for TransactionAcceptor { type Event = Event; + fn name(&self) -> &str { + COMPONENT_NAME + } + fn handle_event( &mut self, effect_builder: EffectBuilder, @@ -904,10 +910,6 @@ impl Component for TransactionAcceptor { } => self.handle_stored_finalized_approvals(effect_builder, event_metadata, is_new), } } - - fn name(&self) -> &str { - COMPONENT_NAME - } } // `allow` can be removed once https://github.com/casper-network/casper-node/issues/3063 is fixed. diff --git a/node/src/components/transaction_acceptor/error.rs b/node/src/components/transaction_acceptor/error.rs index 08c88dfe7d..f3d76c6940 100644 --- a/node/src/components/transaction_acceptor/error.rs +++ b/node/src/components/transaction_acceptor/error.rs @@ -2,9 +2,10 @@ use datasize::DataSize; use serde::Serialize; use thiserror::Error; +use casper_binary_port::ErrorCode as BinaryPortErrorCode; use casper_types::{ - binary_port, AddressableEntityHash, BlockHash, BlockHeader, DeployConfigFailure, Digest, - EntityVersion, InitiatorAddr, PackageHash, Timestamp, TransactionV1ConfigFailure, + AddressableEntityHash, BlockHash, BlockHeader, Digest, EntityVersion, InitiatorAddr, + InvalidTransaction, PackageHash, Timestamp, }; // `allow` can be removed once https://github.com/casper-network/casper-node/issues/3063 is fixed. @@ -15,13 +16,9 @@ pub(crate) enum Error { #[error("block chain has no blocks")] EmptyBlockchain, - /// The deploy has an invalid configuration. - #[error("invalid deploy: {0}")] - InvalidDeployConfiguration(#[from] DeployConfigFailure), - - /// The v1 transaction has an invalid configuration. - #[error("invalid v1 transaction: {0}")] - InvalidV1Configuration(#[from] TransactionV1ConfigFailure), + /// The deploy has an invalid transaction. + #[error("invalid transaction: {0}")] + InvalidTransaction(#[from] InvalidTransaction), /// The transaction is invalid due to missing or otherwise invalid parameters. #[error( @@ -68,16 +65,15 @@ impl Error { } } -impl From for binary_port::ErrorCode { +impl From for BinaryPortErrorCode { fn from(err: Error) -> Self { match err { Error::EmptyBlockchain - | Error::InvalidDeployConfiguration(_) - | Error::InvalidV1Configuration(_) + | Error::InvalidTransaction(_) | Error::Parameters { .. } | Error::Expired { .. } | Error::ExpectedDeploy - | Error::ExpectedTransactionV1 => binary_port::ErrorCode::InvalidTransaction, + | Error::ExpectedTransactionV1 => BinaryPortErrorCode::InvalidTransaction, } } } diff --git a/node/src/components/transaction_acceptor/tests.rs b/node/src/components/transaction_acceptor/tests.rs index 7911255c09..2e6107a20e 100644 --- a/node/src/components/transaction_acceptor/tests.rs +++ b/node/src/components/transaction_acceptor/tests.rs @@ -21,17 +21,20 @@ use thiserror::Error; use tokio::time; use casper_execution_engine::engine_state::MAX_PAYMENT_AMOUNT; -use casper_storage::data_access_layer::{AddressableEntityResult, BalanceResult, QueryResult}; +use casper_storage::{ + data_access_layer::{AddressableEntityResult, BalanceIdentifier, BalanceResult, QueryResult}, + tracking_copy::TrackingCopyError, +}; use casper_types::{ account::{Account, AccountHash, ActionThresholds, AssociatedKeys, Weight}, addressable_entity::{AddressableEntity, NamedKeys}, bytesrepr::Bytes, global_state::TrieMerkleProof, testing::TestRng, - Block, BlockV2, CLValue, Chainspec, ChainspecRawBytes, Contract, Deploy, DeployConfigFailure, - EraId, HashAddr, Package, PublicKey, SecretKey, StoredValue, TestBlockBuilder, TimeDiff, - Timestamp, Transaction, TransactionSessionKind, TransactionV1, TransactionV1Builder, - TransactionV1ConfigFailure, URef, U512, + Block, BlockV2, CLValue, Chainspec, ChainspecRawBytes, Contract, Deploy, EraId, HashAddr, + InvalidDeploy, InvalidTransaction, InvalidTransactionV1, Package, PricingMode, ProtocolVersion, + PublicKey, SecretKey, StoredValue, TestBlockBuilder, TimeDiff, Timestamp, Transaction, + TransactionConfig, TransactionSessionKind, TransactionV1, TransactionV1Builder, URef, U512, }; use super::*; @@ -204,6 +207,7 @@ enum TestScenario { DeployWithoutTransferTarget, DeployWithoutTransferAmount, BalanceCheckForDeploySentByPeer, + InvalidPricingModeForTransactionV1, } impl TestScenario { @@ -243,7 +247,8 @@ impl TestScenario { | TestScenario::FromClientSessionContractPackage(..) | TestScenario::FromClientSignedByAdmin(_) | TestScenario::DeployWithEmptySessionModuleBytes - | TestScenario::DeployWithNativeTransferInPayment => Source::Client, + | TestScenario::DeployWithNativeTransferInPayment + | TestScenario::InvalidPricingModeForTransactionV1 => Source::Client, } } @@ -405,7 +410,7 @@ impl TestScenario { } ContractScenario::MissingContractAtHash => { let txn = TransactionV1Builder::new_targeting_invocable_entity( - EntityAddr::SmartContract(HashAddr::default()), + AddressableEntityHash::new(HashAddr::default()), "call", ) .with_chain_name("casper-example") @@ -417,7 +422,7 @@ impl TestScenario { } ContractScenario::MissingEntryPoint => { let txn = TransactionV1Builder::new_targeting_invocable_entity( - EntityAddr::SmartContract(HashAddr::default()), + AddressableEntityHash::new(HashAddr::default()), "non-existent-entry-point", ) .with_chain_name("casper-example") @@ -467,7 +472,7 @@ impl TestScenario { } ContractPackageScenario::MissingPackageAtHash => { let txn = TransactionV1Builder::new_targeting_package( - PackageAddr::default(), + PackageHash::new(PackageAddr::default()), None, "call", ) @@ -480,7 +485,7 @@ impl TestScenario { } ContractPackageScenario::MissingContractVersion => { let txn = TransactionV1Builder::new_targeting_package( - PackageAddr::default(), + PackageHash::new(PackageAddr::default()), Some(6), "call", ) @@ -550,6 +555,18 @@ impl TestScenario { } } } + TestScenario::InvalidPricingModeForTransactionV1 => { + let classic_mode_transaction = TransactionV1Builder::new_random(rng) + .with_pricing_mode(PricingMode::Classic { + payment_amount: 10000u64, + gas_price_tolerance: 1u8, + standard_payment: true, + }) + .with_chain_name("casper-example") + .build() + .expect("must create classic mode transaction"); + Transaction::from(classic_mode_transaction) + } } } @@ -603,6 +620,7 @@ impl TestScenario { | ContractPackageScenario::MissingContractVersion => false, } } + TestScenario::InvalidPricingModeForTransactionV1 => false, } } @@ -650,46 +668,6 @@ impl reactor::Reactor for Reactor { type Config = TestScenario; type Error = Error; - fn new( - config: Self::Config, - chainspec: Arc, - _chainspec_raw_bytes: Arc, - _network_identity: NetworkIdentity, - registry: &Registry, - _event_queue: EventQueueHandle, - _rng: &mut NodeRng, - ) -> Result<(Self, Effects), Self::Error> { - let (storage_config, storage_tempdir) = storage::Config::new_for_tests(1); - let storage_withdir = WithDir::new(storage_tempdir.path(), storage_config); - - let transaction_acceptor = - TransactionAcceptor::new(Config::default(), chainspec.as_ref(), registry).unwrap(); - - let storage = Storage::new( - &storage_withdir, - None, - ProtocolVersion::from_parts(1, 0, 0), - EraId::default(), - "test", - chainspec.transaction_config.max_ttl.into(), - chainspec.core_config.recent_era_count(), - Some(registry), - false, - ) - .unwrap(); - - let reactor = Reactor { - storage, - transaction_acceptor, - _storage_tempdir: storage_tempdir, - test_scenario: config, - }; - - let effects = Effects::new(); - - Ok((reactor, effects)) - } - fn dispatch_event( &mut self, effect_builder: EffectBuilder, @@ -770,7 +748,47 @@ impl reactor::Reactor for Reactor { request: balance_request, responder, } => { - let key = balance_request.identifier().as_key(); + let key = match balance_request.identifier() { + BalanceIdentifier::Purse(uref) => Key::URef(*uref), + BalanceIdentifier::Public(public_key) => { + Key::Account(public_key.to_account_hash()) + } + BalanceIdentifier::Account(account_hash) + | BalanceIdentifier::PenalizedAccount(account_hash) => { + Key::Account(*account_hash) + } + BalanceIdentifier::Entity(entity_addr) => { + Key::AddressableEntity(*entity_addr) + } + BalanceIdentifier::Internal(addr) => Key::Balance(*addr), + BalanceIdentifier::Payment => { + responder + .respond(BalanceResult::Failure( + TrackingCopyError::NamedKeyNotFound("payment".to_string()), + )) + .ignore::(); + return Effects::new(); + } + BalanceIdentifier::Accumulate => { + responder + .respond(BalanceResult::Failure( + TrackingCopyError::NamedKeyNotFound("accumulate".to_string()), + )) + .ignore::(); + return Effects::new(); + } + }; + let purse_addr = match balance_request.identifier().as_purse_addr() { + Some(purse_addr) => purse_addr, + None => { + responder + .respond(BalanceResult::Failure( + TrackingCopyError::UnexpectedKeyVariant(key), + )) + .ignore::(); + return Effects::new(); + } + }; let proof = TrieMerkleProof::new( key, @@ -790,8 +808,11 @@ impl reactor::Reactor for Reactor { BalanceResult::RootNotFound } else { BalanceResult::Success { - motes: U512::from(motes), - proof: Box::new(proof), + purse_addr, + total_balance: Default::default(), + available_balance: U512::from(motes), + total_balance_proof: Box::new(proof), + balance_holds: Default::default(), } }; responder.respond(balance_result).ignore() @@ -863,6 +884,47 @@ impl reactor::Reactor for Reactor { Event::NetworkRequest(_) => panic!("test does not handle network requests"), } } + + fn new( + config: Self::Config, + chainspec: Arc, + _chainspec_raw_bytes: Arc, + _network_identity: NetworkIdentity, + registry: &Registry, + _event_queue: EventQueueHandle, + _rng: &mut NodeRng, + ) -> Result<(Self, Effects), Self::Error> { + let (storage_config, storage_tempdir) = storage::Config::new_for_tests(1); + let storage_withdir = WithDir::new(storage_tempdir.path(), storage_config); + + let transaction_acceptor = + TransactionAcceptor::new(Config::default(), Arc::clone(&chainspec), registry).unwrap(); + + let storage = Storage::new( + &storage_withdir, + None, + ProtocolVersion::from_parts(1, 0, 0), + EraId::default(), + "test", + chainspec.transaction_config.max_ttl.into(), + chainspec.core_config.recent_era_count(), + Some(registry), + false, + TransactionConfig::default(), + ) + .unwrap(); + + let reactor = Reactor { + storage, + transaction_acceptor, + _storage_tempdir: storage_tempdir, + test_scenario: config, + }; + + let effects = Effects::new(); + + Ok((reactor, effects)) + } } fn put_block_to_storage_and_mark_complete( @@ -1047,6 +1109,7 @@ async fn run_transaction_acceptor_without_timeout( | TestScenario::DeployWithMangledTransferAmount | TestScenario::DeployWithoutTransferTarget | TestScenario::DeployWithoutTransferAmount + | TestScenario::InvalidPricingModeForTransactionV1 | TestScenario::FromClientExpired(_) => { matches!( event, @@ -1243,7 +1306,9 @@ async fn should_reject_invalid_deploy_from_peer() { run_transaction_acceptor(TestScenario::FromPeerInvalidTransaction(TxnType::Deploy)).await; assert!(matches!( result, - Err(super::Error::InvalidDeployConfiguration(_)) + Err(super::Error::InvalidTransaction( + InvalidTransaction::Deploy(_) + )) )) } @@ -1253,7 +1318,7 @@ async fn should_reject_invalid_transaction_v1_from_peer() { run_transaction_acceptor(TestScenario::FromPeerInvalidTransaction(TxnType::V1)).await; assert!(matches!( result, - Err(super::Error::InvalidV1Configuration(_)) + Err(super::Error::InvalidTransaction(InvalidTransaction::V1(_))) )) } @@ -1326,7 +1391,9 @@ async fn should_reject_invalid_deploy_from_client() { run_transaction_acceptor(TestScenario::FromClientInvalidTransaction(TxnType::Deploy)).await; assert!(matches!( result, - Err(super::Error::InvalidDeployConfiguration(_)) + Err(super::Error::InvalidTransaction( + InvalidTransaction::Deploy(_) + )) )) } @@ -1336,7 +1403,7 @@ async fn should_reject_invalid_transaction_v1_from_client() { run_transaction_acceptor(TestScenario::FromClientInvalidTransaction(TxnType::V1)).await; assert!(matches!( result, - Err(super::Error::InvalidV1Configuration(_)) + Err(super::Error::InvalidTransaction(InvalidTransaction::V1(_))) )) } @@ -1366,8 +1433,8 @@ async fn should_reject_future_dated_deploy_from_client() { .await; assert!(matches!( result, - Err(super::Error::InvalidDeployConfiguration( - DeployConfigFailure::TimestampInFuture { .. } + Err(super::Error::InvalidTransaction( + InvalidTransaction::Deploy(InvalidDeploy::TimestampInFuture { .. }) )) )) } @@ -1378,9 +1445,9 @@ async fn should_reject_future_dated_transaction_v1_from_client() { run_transaction_acceptor(TestScenario::FromClientFutureDatedTransaction(TxnType::V1)).await; assert!(matches!( result, - Err(super::Error::InvalidV1Configuration( - TransactionV1ConfigFailure::TimestampInFuture { .. } - )) + Err(super::Error::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::TimestampInFuture { .. } + ))) )) } @@ -2175,8 +2242,8 @@ async fn should_reject_deploy_without_transfer_amount() { let result = run_transaction_acceptor(test_scenario).await; assert!(matches!( result, - Err(super::Error::InvalidDeployConfiguration( - DeployConfigFailure::MissingTransferAmount + Err(super::Error::InvalidTransaction( + InvalidTransaction::Deploy(InvalidDeploy::MissingTransferAmount) )) )) } @@ -2200,8 +2267,8 @@ async fn should_reject_deploy_with_mangled_transfer_amount() { let result = run_transaction_acceptor(test_scenario).await; assert!(matches!( result, - Err(super::Error::InvalidDeployConfiguration( - DeployConfigFailure::FailedToParseTransferAmount + Err(super::Error::InvalidTransaction( + InvalidTransaction::Deploy(InvalidDeploy::FailedToParseTransferAmount) )) )) } @@ -2255,3 +2322,15 @@ async fn should_accept_transaction_v1_signed_by_admin_from_client() { let result = run_transaction_acceptor(test_scenario).await; assert!(result.is_ok()) } + +#[tokio::test] +async fn should_reject_transaction_v1_with_invalid_pricing_mode() { + let test_scenario = TestScenario::InvalidPricingModeForTransactionV1; + let result = run_transaction_acceptor(test_scenario).await; + assert!(matches!( + result, + Err(super::Error::InvalidTransaction(InvalidTransaction::V1( + InvalidTransactionV1::InvalidPricingMode { .. } + ))) + )) +} diff --git a/node/src/components/transaction_buffer.rs b/node/src/components/transaction_buffer.rs index 4ec2ad04cd..12d8509042 100644 --- a/node/src/components/transaction_buffer.rs +++ b/node/src/components/transaction_buffer.rs @@ -39,7 +39,7 @@ use crate::{ storage::Storage, types::{ appendable_block::{AddError, AppendableBlock}, - FinalizedBlock, TransactionExt, TransactionFootprint, + FinalizedBlock, TransactionFootprint, }, NodeRng, }; @@ -254,10 +254,6 @@ impl TransactionBuffer { error!(%transaction_hash, "TransactionBuffer: invalid transaction must not be buffered"); return; } - if self.dead.contains(&transaction_hash) { - info!(%transaction_hash, "TransactionBuffer: attempt to register already dead transaction"); - return; - } if self .hold .values() @@ -266,10 +262,10 @@ impl TransactionBuffer { info!(%transaction_hash, "TransactionBuffer: attempt to register already held transaction"); return; } - let footprint = match transaction.footprint(&self.chainspec) { - Some(footprint) => footprint, - None => { - error!(%transaction_hash, "TransactionBuffer: unable to created transaction footprint"); + let footprint = match TransactionFootprint::new(&self.chainspec, &transaction) { + Ok(footprint) => footprint, + Err(invalid_transaction_error) => { + error!(%transaction_hash, ?invalid_transaction_error, "TransactionBuffer: unable to created transaction footprint"); return; } }; @@ -395,7 +391,7 @@ impl TransactionBuffer { .filter(|(th, _)| !self.dead.contains(th)) .filter(|(_, (_, maybe_data))| match maybe_data { None => false, - Some(footprint) => footprint.gas_tolerance() >= (current_era_gas_price as u64), + Some(footprint) => footprint.gas_price_tolerance() >= (current_era_gas_price), }) .filter_map(|(th, (_, maybe_data))| { maybe_data diff --git a/node/src/components/transaction_buffer/tests.rs b/node/src/components/transaction_buffer/tests.rs index 437862f0ec..5d6e1d7191 100644 --- a/node/src/components/transaction_buffer/tests.rs +++ b/node/src/components/transaction_buffer/tests.rs @@ -356,6 +356,7 @@ fn get_appendable_block_when_transfers_are_of_one_category() { block_max_install_upgrade_count: 0, block_max_standard_count: 10, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -386,6 +387,7 @@ fn get_appendable_block_when_transfers_are_both_legacy_and_v1() { block_max_install_upgrade_count: 0, block_max_standard_count: 10, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -417,6 +419,7 @@ fn get_appendable_block_when_standards_are_of_one_category() { block_max_install_upgrade_count: 0, block_max_standard_count: 10, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -446,6 +449,7 @@ fn get_appendable_block_when_standards_are_both_legacy_and_v1() { block_max_install_upgrade_count: 0, block_max_standard_count: 10, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; let chainspec = Chainspec { @@ -485,6 +489,7 @@ fn block_fully_saturated() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -585,6 +590,7 @@ fn block_not_fully_saturated() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -689,6 +695,7 @@ fn excess_transactions_do_not_sneak_into_transfer_bucket() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -753,6 +760,7 @@ fn excess_transactions_do_not_sneak_into_staking_bucket() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -817,6 +825,7 @@ fn excess_transactions_do_not_sneak_into_install_upgrades_bucket() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; @@ -881,6 +890,7 @@ fn excess_transactions_do_not_sneak_into_standards_bucket() { block_max_install_upgrade_count: max_install_upgrade, block_max_standard_count: max_standard, block_max_approval_count: 210, + block_gas_limit: u64::MAX, // making sure this test does not hit gas limit first ..Default::default() }; diff --git a/node/src/components/upgrade_watcher.rs b/node/src/components/upgrade_watcher.rs index e235f984ed..e849a2e52d 100644 --- a/node/src/components/upgrade_watcher.rs +++ b/node/src/components/upgrade_watcher.rs @@ -316,7 +316,7 @@ impl UpgradePoint { fn from_chainspec_path + std::fmt::Debug>(path: P) -> Result { let bytes = file_utils::read_file(path.as_ref().join(CHAINSPEC_FILENAME)) .map_err(Error::LoadUpgradePoint)?; - Ok(toml::from_slice(&bytes)?) + Ok(toml::from_str(std::str::from_utf8(&bytes).unwrap())?) } } @@ -523,11 +523,9 @@ mod tests { fs::create_dir(&subdir).unwrap(); let path = subdir.join(CHAINSPEC_FILENAME); - fs::write( - path, - toml::to_string_pretty(&chainspec).expect("should encode to toml"), - ) - .expect("should install chainspec"); + + let pretty = toml::to_string_pretty(&chainspec); + fs::write(path, pretty.expect("should encode to toml")).expect("should install chainspec"); chainspec } @@ -541,20 +539,20 @@ mod tests { let mut rng = crate::new_rng(); - let mut current = ProtocolVersion::from_parts(0, 9, 9); - let v1_0_0 = ProtocolVersion::from_parts(1, 0, 0); - let chainspec_v1_0_0 = install_chainspec(&mut rng, tempdir.path(), &v1_0_0); + let mut current = ProtocolVersion::from_parts(1, 9, 9); + let v2_0_0 = ProtocolVersion::from_parts(2, 0, 0); + let chainspec_v2_0_0 = install_chainspec(&mut rng, tempdir.path(), &v2_0_0); assert_eq!( next_point(¤t), - chainspec_v1_0_0.protocol_config.into() + chainspec_v2_0_0.protocol_config.into() ); - current = v1_0_0; - let v1_0_3 = ProtocolVersion::from_parts(1, 0, 3); - let chainspec_v1_0_3 = install_chainspec(&mut rng, tempdir.path(), &v1_0_3); + current = v2_0_0; + let v2_0_3 = ProtocolVersion::from_parts(2, 0, 3); + let chainspec_v2_0_3 = install_chainspec(&mut rng, tempdir.path(), &v2_0_3); assert_eq!( next_point(¤t), - chainspec_v1_0_3.protocol_config.into() + chainspec_v2_0_3.protocol_config.into() ); } diff --git a/node/src/effect.rs b/node/src/effect.rs index 6a9c5c14c7..be16469130 100644 --- a/node/src/effect.rs +++ b/node/src/effect.rs @@ -114,29 +114,27 @@ use smallvec::{smallvec, SmallVec}; use tokio::{sync::Semaphore, time}; use tracing::{debug, error, warn}; -use casper_execution_engine::engine_state::{self}; -use casper_storage::data_access_layer::{ - tagged_values::{TaggedValuesRequest, TaggedValuesResult}, - BalanceRequest, BalanceResult, QueryRequest, QueryResult, +use casper_binary_port::{ + ConsensusStatus, ConsensusValidatorChanges, LastProgress, NetworkName, RecordId, Uptime, }; - -use casper_storage::data_access_layer::{ - AddressableEntityResult, EraValidatorsRequest, EraValidatorsResult, - ExecutionResultsChecksumResult, PutTrieRequest, PutTrieResult, RoundSeigniorageRateRequest, - RoundSeigniorageRateResult, TotalSupplyRequest, TotalSupplyResult, TrieRequest, TrieResult, +use casper_storage::{ + block_store::types::ApprovalsHashes, + data_access_layer::{ + tagged_values::{TaggedValuesRequest, TaggedValuesResult}, + AddressableEntityResult, BalanceRequest, BalanceResult, EraValidatorsRequest, + EraValidatorsResult, ExecutionResultsChecksumResult, PutTrieRequest, PutTrieResult, + QueryRequest, QueryResult, RoundSeigniorageRateRequest, RoundSeigniorageRateResult, + TotalSupplyRequest, TotalSupplyResult, TrieRequest, TrieResult, + }, + DbRawBytesSpec, }; use casper_types::{ - binary_port::{ - ConsensusStatus, ConsensusValidatorChanges, DbRawBytesSpec, LastProgress, NetworkName, - RecordId, SpeculativeExecutionResult, Uptime, - }, execution::{Effects as ExecutionEffects, ExecutionResult}, - package::Package, Approval, AvailableBlockRange, Block, BlockHash, BlockHeader, BlockSignatures, BlockSynchronizerStatus, BlockV2, ChainspecRawBytes, DeployHash, Digest, EraId, ExecutionInfo, - FinalitySignature, FinalitySignatureId, FinalitySignatureV2, Key, NextUpgrade, ProtocolVersion, - PublicKey, Timestamp, Transaction, TransactionHash, TransactionHeader, TransactionId, Transfer, - U512, + FinalitySignature, FinalitySignatureId, FinalitySignatureV2, Key, NextUpgrade, Package, + ProtocolVersion, PublicKey, Timestamp, Transaction, TransactionHash, TransactionHeader, + TransactionId, Transfer, U512, }; use crate::{ @@ -146,13 +144,13 @@ use crate::{ TrieAccumulatorResponse, }, consensus::{ClContext, EraDump, ProposedBlock}, + contract_runtime::SpeculativeExecutionResult, diagnostics_port::StopAtSpec, fetcher::{FetchItem, FetchResult}, gossiper::GossipItem, network::{blocklist::BlocklistJustification, FromIncoming, NetworkInsights}, transaction_acceptor, }, - contract_runtime::SpeculativeExecutionState, failpoints::FailpointActivation, reactor::{main_reactor::ReactorState, EventQueueHandle, QueueKind}, types::{ @@ -162,9 +160,6 @@ use crate::{ }, utils::{fmt_limit::FmtLimit, SharedFlag, Source}, }; -use casper_storage::block_store::types::ApprovalsHashes; - -use crate::effect::requests::TransactionBufferRequest; use announcements::{ BlockAccumulatorAnnouncement, ConsensusAnnouncement, ContractRuntimeAnnouncement, ControlAnnouncement, FatalAnnouncement, FetchedNewBlockAnnouncement, @@ -178,7 +173,8 @@ use requests::{ BlockSynchronizerRequest, BlockValidationRequest, ChainspecRawBytesRequest, ConsensusRequest, ContractRuntimeRequest, FetcherRequest, MakeBlockExecutableRequest, MarkBlockCompletedRequest, MetricsRequest, NetworkInfoRequest, NetworkRequest, ReactorInfoRequest, SetNodeStopRequest, - StorageRequest, SyncGlobalStateRequest, TrieAccumulatorRequest, UpgradeWatcherRequest, + StorageRequest, SyncGlobalStateRequest, TransactionBufferRequest, TrieAccumulatorRequest, + UpgradeWatcherRequest, }; /// A resource that will never be available, thus trying to acquire it will wait forever. @@ -926,7 +922,7 @@ impl EffectBuilder { pub(crate) async fn try_accept_transaction( self, transaction: Transaction, - speculative_exec_at_block: Option>, + is_speculative: bool, ) -> Result<(), transaction_acceptor::Error> where REv: From, @@ -934,7 +930,7 @@ impl EffectBuilder { self.make_request( |responder| AcceptTransactionRequest { transaction, - speculative_exec_at_block, + is_speculative, responder, }, QueueKind::Api, @@ -1164,7 +1160,7 @@ impl EffectBuilder { |responder| StorageRequest::GetBlockUtilizationScore { era_id, block_height, - transaction_count, + switch_block_utilization: transaction_count, responder, }, QueueKind::FromStorage, @@ -1686,7 +1682,7 @@ impl EffectBuilder { /// Stores the given execution results for the transactions in the given block in the linear /// block store. - pub(crate) async fn put_execution_results_to_storage( + pub(crate) async fn put_execution_artifacts_to_storage( self, block_hash: BlockHash, block_height: u64, @@ -2283,15 +2279,15 @@ impl EffectBuilder { /// used for debugging & discovery purposes. pub(crate) async fn speculatively_execute( self, - execution_prestate: SpeculativeExecutionState, + block_header: Box, transaction: Box, - ) -> Result + ) -> SpeculativeExecutionResult where REv: From, { self.make_request( |responder| ContractRuntimeRequest::SpeculativelyExecute { - execution_prestate, + block_header, transaction, responder, }, diff --git a/node/src/effect/requests.rs b/node/src/effect/requests.rs index 4a9ada14c6..c1dac727cd 100644 --- a/node/src/effect/requests.rs +++ b/node/src/effect/requests.rs @@ -15,24 +15,26 @@ use serde::Serialize; use smallvec::SmallVec; use static_assertions::const_assert; -use casper_execution_engine::engine_state::{self}; -use casper_storage::data_access_layer::{ - tagged_values::{TaggedValuesRequest, TaggedValuesResult}, - AddressableEntityResult, BalanceRequest, BalanceResult, EraValidatorsRequest, - EraValidatorsResult, ExecutionResultsChecksumResult, PutTrieRequest, PutTrieResult, - QueryRequest, QueryResult, RoundSeigniorageRateRequest, RoundSeigniorageRateResult, - TotalSupplyRequest, TotalSupplyResult, TrieRequest, TrieResult, +use casper_binary_port::{ + ConsensusStatus, ConsensusValidatorChanges, LastProgress, NetworkName, RecordId, Uptime, +}; +use casper_storage::{ + block_store::types::ApprovalsHashes, + data_access_layer::{ + tagged_values::{TaggedValuesRequest, TaggedValuesResult}, + AddressableEntityResult, BalanceRequest, BalanceResult, EraValidatorsRequest, + EraValidatorsResult, ExecutionResultsChecksumResult, PutTrieRequest, PutTrieResult, + QueryRequest, QueryResult, RoundSeigniorageRateRequest, RoundSeigniorageRateResult, + TotalSupplyRequest, TotalSupplyResult, TrieRequest, TrieResult, + }, + DbRawBytesSpec, }; use casper_types::{ - binary_port::{ - ConsensusStatus, ConsensusValidatorChanges, DbRawBytesSpec, LastProgress, NetworkName, - RecordId, SpeculativeExecutionResult, Uptime, - }, - execution::ExecutionResult, - Approval, AvailableBlockRange, Block, BlockHash, BlockHeader, BlockSignatures, - BlockSynchronizerStatus, BlockV2, ChainspecRawBytes, DeployHash, Digest, DisplayIter, EraId, - ExecutionInfo, FinalitySignature, FinalitySignatureId, Key, NextUpgrade, ProtocolVersion, - PublicKey, Timestamp, Transaction, TransactionHash, TransactionHeader, TransactionId, Transfer, + execution::ExecutionResult, Approval, AvailableBlockRange, Block, BlockHash, BlockHeader, + BlockSignatures, BlockSynchronizerStatus, BlockV2, ChainspecRawBytes, DeployHash, Digest, + DisplayIter, EraId, ExecutionInfo, FinalitySignature, FinalitySignatureId, Key, NextUpgrade, + ProtocolVersion, PublicKey, Timestamp, Transaction, TransactionHash, TransactionHeader, + TransactionId, Transfer, }; use super::{AutoClosingResponder, GossipTarget, Responder}; @@ -43,13 +45,13 @@ use crate::{ TrieAccumulatorResponse, }, consensus::{ClContext, ProposedBlock}, + contract_runtime::SpeculativeExecutionResult, diagnostics_port::StopAtSpec, fetcher::{FetchItem, FetchResult}, gossiper::GossipItem, network::NetworkInsights, transaction_acceptor, }, - contract_runtime::SpeculativeExecutionState, reactor::main_reactor::ReactorState, types::{ appendable_block::AppendableBlock, BlockExecutionResultsOrChunk, @@ -58,7 +60,6 @@ use crate::{ }, utils::Source, }; -use casper_storage::block_store::types::ApprovalsHashes; const _STORAGE_REQUEST_SIZE: usize = mem::size_of::(); const_assert!(_STORAGE_REQUEST_SIZE < 129); @@ -492,10 +493,15 @@ pub(crate) enum StorageRequest { }, /// Retrieve the height of the final block of the previous protocol version, if known. GetKeyBlockHeightForActivationPoint { responder: Responder> }, + /// Retrieve the block utilization score. GetBlockUtilizationScore { + /// The era id. era_id: EraId, + /// The block height of the switch block block_height: u64, - transaction_count: u64, + /// The utilization within the switch block. + switch_block_utilization: u64, + /// Responder, responded once the utilization for the era has been determined. responder: Responder>, }, } @@ -833,12 +839,12 @@ pub(crate) enum ContractRuntimeRequest { }, /// Execute transaction without committing results SpeculativelyExecute { - /// Hash of a block on top of which to execute the transaction. - execution_prestate: SpeculativeExecutionState, + /// Pre-state. + block_header: Box, /// Transaction to execute. transaction: Box, /// Results - responder: Responder>, + responder: Responder, }, UpdateRuntimePrice(EraId, u8), GetEraGasPrice { @@ -919,15 +925,15 @@ impl Display for ContractRuntimeRequest { write!(formatter, "trie: {:?}", request) } ContractRuntimeRequest::SpeculativelyExecute { - execution_prestate, transaction, + block_header, .. } => { write!( formatter, "Execute {} on {}", transaction.hash(), - execution_prestate.state_root_hash + block_header.state_root_hash() ) } ContractRuntimeRequest::UpdateRuntimePrice(_, era_gas_price) => { @@ -1167,20 +1173,17 @@ impl Display for SetNodeStopRequest { #[derive(DataSize, Debug, Serialize)] pub(crate) struct AcceptTransactionRequest { pub(crate) transaction: Transaction, - pub(crate) speculative_exec_at_block: Option>, + pub(crate) is_speculative: bool, pub(crate) responder: Responder>, } impl Display for AcceptTransactionRequest { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if self.speculative_exec_at_block.is_some() { - write!( - f, - "accept transaction {} for speculative exec", - self.transaction.hash() - ) - } else { - write!(f, "accept transaction {}", self.transaction.hash()) - } + write!( + f, + "accept transaction {} is_speculative: {}", + self.transaction.hash(), + self.is_speculative + ) } } diff --git a/node/src/reactor/main_reactor.rs b/node/src/reactor/main_reactor.rs index 4b1e055f59..f03845a735 100644 --- a/node/src/reactor/main_reactor.rs +++ b/node/src/reactor/main_reactor.rs @@ -25,8 +25,8 @@ use memory_metrics::MemoryMetrics; use prometheus::Registry; use tracing::{debug, error, info, warn}; +use casper_binary_port::{LastProgress, NetworkName, Uptime}; use casper_types::{ - binary_port::{LastProgress, NetworkName, Uptime}, Block, BlockHash, BlockV2, Chainspec, ChainspecRawBytes, EraId, FinalitySignature, FinalitySignatureV2, PublicKey, TimeDiff, Timestamp, Transaction, U512, }; @@ -722,11 +722,11 @@ impl reactor::Reactor for MainReactor { ), MainEvent::AcceptTransactionRequest(AcceptTransactionRequest { transaction, - speculative_exec_at_block, + is_speculative, responder, }) => { - let source = if let Some(block) = speculative_exec_at_block { - Source::SpeculativeExec(block) + let source = if is_speculative { + Source::SpeculativeExec } else { Source::Client }; @@ -786,7 +786,7 @@ impl reactor::Reactor for MainReactor { ), )); } - Source::SpeculativeExec(_) => { + Source::SpeculativeExec => { error!( %transaction, "transaction acceptor should not announce speculative exec transactions" @@ -1111,6 +1111,7 @@ impl reactor::Reactor for MainReactor { chainspec.core_config.recent_era_count(), Some(registry), config.node.force_resync, + chainspec.transaction_config, )?; let contract_runtime = ContractRuntime::new( @@ -1205,8 +1206,11 @@ impl reactor::Reactor for MainReactor { ); let upgrade_watcher = UpgradeWatcher::new(chainspec.as_ref(), config.upgrade_watcher, &root_dir)?; - let transaction_acceptor = - TransactionAcceptor::new(config.transaction_acceptor, chainspec.as_ref(), registry)?; + let transaction_acceptor = TransactionAcceptor::new( + config.transaction_acceptor, + Arc::clone(&chainspec), + registry, + )?; let transaction_buffer = TransactionBuffer::new(Arc::clone(&chainspec), config.transaction_buffer, registry)?; @@ -1672,7 +1676,7 @@ impl MainReactor { for exec_artifact in fwd_meta_block.execution_results.iter() { let event = event_stream_server::Event::TransactionProcessed { transaction_hash: exec_artifact.transaction_hash, - transaction_header: Box::new(exec_artifact.header.clone()), + transaction_header: Box::new(exec_artifact.transaction_header.clone()), block_hash: *fwd_meta_block.block.hash(), execution_result: Box::new(exec_artifact.execution_result.clone()), messages: exec_artifact.messages.clone(), diff --git a/node/src/reactor/main_reactor/tests.rs b/node/src/reactor/main_reactor/tests.rs index 7f48d8e524..b0ea8993ed 100644 --- a/node/src/reactor/main_reactor/tests.rs +++ b/node/src/reactor/main_reactor/tests.rs @@ -1,4 +1,5 @@ mod binary_port; +mod transactions; use std::{ collections::{BTreeMap, BTreeSet}, @@ -11,6 +12,7 @@ use std::{ }; use either::Either; +use itertools::Itertools; use num::Zero; use num_rational::Ratio; use num_traits::One; @@ -20,10 +22,16 @@ use tokio::time::{self, error::Elapsed}; use tracing::{error, info}; use casper_storage::{ - data_access_layer::{BidsRequest, BidsResult, TotalSupplyRequest, TotalSupplyResult}, + data_access_layer::{ + balance::{BalanceHandling, BalanceResult}, + AddressableEntityRequest, AddressableEntityResult, BalanceRequest, BidsRequest, BidsResult, + TotalSupplyRequest, TotalSupplyResult, + }, global_state::state::{StateProvider, StateReader}, }; use casper_types::{ + account::AccountHash, + crypto, execution::{ExecutionResult, ExecutionResultV2, TransformKindV2, TransformV2}, system::{ auction::{BidAddr, BidKind, BidsExt, DelegationRate}, @@ -32,9 +40,10 @@ use casper_types::{ testing::TestRng, AccountConfig, AccountsConfig, ActivationPoint, AddressableEntityHash, AvailableBlockRange, Block, BlockHash, BlockHeader, BlockV2, CLValue, Chainspec, ChainspecRawBytes, - ConsensusProtocolName, Deploy, EraId, Key, Motes, NextUpgrade, ProtocolVersion, PublicKey, - Rewards, SecretKey, StoredValue, SystemEntityRegistry, TimeDiff, Timestamp, Transaction, - TransactionHash, ValidatorConfig, U512, + ConsensusProtocolName, Deploy, EraId, FeeHandling, Gas, HoldsEpoch, Key, Motes, NextUpgrade, + PricingHandling, PricingMode, ProtocolVersion, PublicKey, RefundHandling, Rewards, SecretKey, + StoredValue, SystemEntityRegistry, TimeDiff, Timestamp, Transaction, TransactionHash, + TransactionV1Builder, ValidatorConfig, U512, }; use crate::{ @@ -104,6 +113,54 @@ struct ConfigsOverride { min_gas_price: u8, upper_threshold: u64, lower_threshold: u64, + refund_handling_override: Option, + fee_handling_override: Option, + pricing_handling_override: Option, + allow_reservations_override: Option, + balance_hold_interval_override: Option, +} + +impl ConfigsOverride { + fn with_refund_handling(mut self, refund_handling: RefundHandling) -> Self { + self.refund_handling_override = Some(refund_handling); + self + } + + fn with_fee_handling(mut self, fee_handling: FeeHandling) -> Self { + self.fee_handling_override = Some(fee_handling); + self + } + + fn with_pricing_handling(mut self, pricing_handling: PricingHandling) -> Self { + self.pricing_handling_override = Some(pricing_handling); + self + } + + #[allow(unused)] + fn with_allow_reservations(mut self, allow_reservations: bool) -> Self { + self.allow_reservations_override = Some(allow_reservations); + self + } + + fn with_balance_hold_interval(mut self, balance_hold_interval: TimeDiff) -> Self { + self.balance_hold_interval_override = Some(balance_hold_interval); + self + } + + fn with_min_gas_price(mut self, min_gas_price: u8) -> Self { + self.min_gas_price = min_gas_price; + self + } + + fn with_max_gas_price(mut self, max_gas_price: u8) -> Self { + self.max_gas_price = max_gas_price; + self + } + + fn with_minimum_era_height(mut self, minimum_era_height: u64) -> Self { + self.minimum_era_height = minimum_era_height; + self + } } impl Default for ConfigsOverride { @@ -127,6 +184,11 @@ impl Default for ConfigsOverride { min_gas_price: 1, upper_threshold: 90, lower_threshold: 50, + refund_handling_override: None, + fee_handling_override: None, + pricing_handling_override: None, + allow_reservations_override: None, + balance_hold_interval_override: None, } } } @@ -192,8 +254,8 @@ impl TestFixture { let (mut chainspec, chainspec_raw_bytes) = <(Chainspec, ChainspecRawBytes)>::from_resources("local"); - let min_motes = 1_000_000_000_000u64; // 1000 token - let max_motes = min_motes * 100; // 100_000 token + let min_motes = 100_000_000_000_000_000u64; + let max_motes = min_motes * 100; let balance = U512::from(rng.gen_range(min_motes..max_motes)); // Override accounts with those generated from the keys. @@ -240,6 +302,11 @@ impl TestFixture { min_gas_price: min, upper_threshold: go_up, lower_threshold: go_down, + refund_handling_override, + fee_handling_override, + pricing_handling_override, + allow_reservations_override, + balance_hold_interval_override, } = spec_override.unwrap_or_default(); if era_duration != TimeDiff::from_millis(0) { chainspec.core_config.era_duration = era_duration; @@ -265,6 +332,22 @@ impl TestFixture { chainspec.core_config.minimum_block_time * 2; chainspec.core_config.signature_rewards_max_delay = signature_rewards_max_delay; + if let Some(refund_handling) = refund_handling_override { + chainspec.core_config.refund_handling = refund_handling; + } + if let Some(fee_handling) = fee_handling_override { + chainspec.core_config.fee_handling = fee_handling; + } + if let Some(pricing_handling) = pricing_handling_override { + chainspec.core_config.pricing_handling = pricing_handling; + } + if let Some(allow_reservations) = allow_reservations_override { + chainspec.core_config.allow_reservations = allow_reservations; + } + if let Some(balance_hold_interval) = balance_hold_interval_override { + chainspec.core_config.balance_hold_interval = balance_hold_interval; + } + let mut fixture = TestFixture { rng, node_contexts: vec![], @@ -555,11 +638,30 @@ impl TestFixture { self.try_run_until( move |nodes: &Nodes| { nodes.values().all(|runner| { - runner + if runner .main_reactor() .storage() .read_execution_result(txn_hash) .is_some() + { + let exec_info = runner + .main_reactor() + .storage() + .read_execution_info(*txn_hash); + + if let Some(exec_info) = exec_info { + runner + .main_reactor() + .storage() + .read_block_header_by_height(exec_info.block_height, true) + .unwrap() + .is_some() + } else { + false + } + } else { + false + } }) }, within, @@ -611,7 +713,6 @@ impl TestFixture { .storage .read_highest_block() .expect("should have block"); - let bids_request = BidsRequest::new(*highest_block.state_root_hash()); let bids_result = runner .main_reactor() @@ -662,7 +763,7 @@ impl TestFixture { .expect("should have block"); // we need the native auction addr so we can directly call it w/o wasm - // we can get it out of the system contract registry which is just a + // we can get it out of the system entity registry which is just a // value in global state under a stable key. let maybe_registry = reactor .contract_runtime @@ -674,14 +775,14 @@ impl TestFixture { .expect("should not have gs storage error") .expect("should have stored value"); - let system_contract_registry: SystemEntityRegistry = match maybe_registry { + let system_entity_registry: SystemEntityRegistry = match maybe_registry { StoredValue::CLValue(cl_value) => CLValue::into_t(cl_value).unwrap(), _ => { panic!("expected CLValue") } }; - *system_contract_registry.get(system_contract_name).unwrap() + *system_entity_registry.get(system_contract_name).unwrap() } #[track_caller] @@ -698,6 +799,53 @@ impl TestFixture { price.gas_price() } + #[track_caller] + fn check_account_balance_hold_at_tip(&self, account_public_key: PublicKey) -> U512 { + let (_, runner) = self + .network + .nodes() + .iter() + .next() + .expect("must have runner"); + + let highest_block = runner + .main_reactor() + .storage + .read_highest_block() + .expect("should have block"); + + let block_time = highest_block.clone_header().timestamp(); + + let holds_epoch = HoldsEpoch::from_timestamp( + block_time, + self.chainspec.core_config.balance_hold_interval, + ); + + let balance_request = BalanceRequest::from_public_key( + *highest_block.state_root_hash(), + highest_block.protocol_version(), + account_public_key, + BalanceHandling::Available { holds_epoch }, + ); + + let balance_result = runner + .main_reactor() + .contract_runtime + .data_access_layer() + .balance(balance_request); + + if let BalanceResult::Success { balance_holds, .. } = balance_result { + balance_holds + .values() + .flat_map(|holds| holds.values().map(|(v, _)| *v)) + .collect_vec() + .into_iter() + .sum() + } else { + panic!("failed balance result") + } + } + async fn inject_transaction(&mut self, txn: Transaction) { // saturate the network with the transactions via just making them all store and accept it // they're all validators so one of them should propose it @@ -741,18 +889,20 @@ impl TestFixture { .expect("node 0 should have given execution result") { ExecutionResult::V1(_) => unreachable!(), - ExecutionResult::V2(ExecutionResultV2::Success { effects, .. }) => { - effects.transforms().to_vec() - } - ExecutionResult::V2(ExecutionResultV2::Failure { - cost, + ExecutionResult::V2(ExecutionResultV2 { + effects, + consumed: gas, error_message, .. }) => { - panic!( - "transaction execution failed: {} cost: {}", - error_message, cost - ); + if error_message.is_none() { + effects.transforms().to_vec() + } else { + panic!( + "transaction execution failed: {:?} gas: {}", + error_message, gas + ); + } } } } @@ -1360,11 +1510,11 @@ async fn should_store_finalized_approvals() { // Run until the transaction gets executed. let has_stored_exec_results = |nodes: &Nodes| { nodes.values().all(|runner| { - runner + let read = runner .main_reactor() .storage() - .read_execution_result(&transaction_hash) - .is_some() + .read_execution_result(&transaction_hash); + read.is_some() }) }; fixture.run_until(has_stored_exec_results, ONE_MIN).await; @@ -1728,7 +1878,7 @@ async fn run_redelegate_bid_network() { // Inject the transaction and run the network until executed. fixture.inject_transaction(txn).await; fixture - .run_until_executed_transaction(&txn_hash, TEN_SECS) + .run_until_executed_transaction(&txn_hash, ONE_MIN) .await; // Ensure execution succeeded and that there is a Write transform for the bid's key. @@ -1736,6 +1886,7 @@ async fn run_redelegate_bid_network() { &bob_public_key, Some(&alice_public_key), )); + fixture .successful_execution_transforms(&txn_hash) .iter() @@ -1763,18 +1914,18 @@ async fn run_redelegate_bid_network() { ); deploy.sign(&alice_secret_key); - let txn = Transaction::Deploy(deploy); - let txn_hash = txn.hash(); + let transaction = Transaction::Deploy(deploy); + let transaction_hash = transaction.hash(); // Inject the transaction and run the network until executed. - fixture.inject_transaction(txn).await; + fixture.inject_transaction(transaction).await; fixture - .run_until_executed_transaction(&txn_hash, TEN_SECS) + .run_until_executed_transaction(&transaction_hash, TEN_SECS) .await; // Ensure execution succeeded and that there is a Prune transform for the bid's key. fixture - .successful_execution_transforms(&txn_hash) + .successful_execution_transforms(&transaction_hash) .iter() .find(|transform| match transform.kind() { TransformKindV2::Prune(prune_key) => prune_key == &bid_key, @@ -1831,10 +1982,13 @@ async fn rewards_are_calculated() { const STAKE: u128 = 1000000000; const PRIME_STAKES: [u128; 5] = [106907, 106921, 106937, 106949, 106957]; const ERA_COUNT: u64 = 3; -const ERA_DURATION: u64 = 20000; //milliseconds +const ERA_DURATION: u64 = 20000; +//milliseconds const MIN_HEIGHT: u64 = 6; -const BLOCK_TIME: u64 = 2000; //milliseconds -const TIME_OUT: u64 = 600; //seconds +const BLOCK_TIME: u64 = 2000; +//milliseconds +const TIME_OUT: u64 = 600; +//seconds const SEIGNIORAGE: (u64, u64) = (1u64, 100u64); const REPRESENTATIVE_NODE_INDEX: usize = 0; // Parameters we generally want to vary @@ -2490,9 +2644,6 @@ async fn should_raise_gas_price_to_ceiling_and_reduce_to_floor() { minimum_era_height: 5, lower_threshold: 0, upper_threshold: 1, - max_standard_count: 1, - max_staking_count: 1, - max_install_count: 1, max_transfer_count: 1, max_gas_price, ..Default::default() @@ -2509,22 +2660,23 @@ async fn should_raise_gas_price_to_ceiling_and_reduce_to_floor() { let switch_block = fixture.switch_block(ERA_ONE); let mut current_era = switch_block.era_id(); + let chain_name = fixture.chainspec.network_config.name.clone(); // Run the network at load for at least 5 eras. for _ in 0..5 { let target_public_key = PublicKey::random(&mut fixture.rng); - let mut native_transfer = Deploy::native_transfer( - fixture.chainspec.network_config.name.clone(), - alice_public_key.clone(), - target_public_key, - None, - Timestamp::now(), - TimeDiff::from_seconds(1200), - max_gas_price as u64, - ); + let fixed_native_mint_transaction = + TransactionV1Builder::new_transfer(10_000_000_000u64, None, target_public_key, None) + .expect("must get builder") + .with_chain_name(chain_name.clone()) + .with_secret_key(&alice_secret_key) + .with_pricing_mode(PricingMode::Fixed { + gas_price_tolerance: max_gas_price, + }) + .build() + .expect("must get transaction"); - native_transfer.sign(&alice_secret_key); - let txn = Transaction::Deploy(native_transfer); + let txn = Transaction::V1(fixed_native_mint_transaction); fixture.inject_transaction(txn).await; let next_era = current_era.successor(); fixture @@ -2536,6 +2688,39 @@ async fn should_raise_gas_price_to_ceiling_and_reduce_to_floor() { let expected_gas_price = fixture.chainspec.vacancy_config.max_gas_price; let actual_gas_price = fixture.get_current_era_price(); assert_eq!(actual_gas_price, expected_gas_price); + let target_public_key = PublicKey::random(&mut fixture.rng); + + let holds_before = fixture.check_account_balance_hold_at_tip(alice_public_key.clone()); + let amount = 10_000_000_000u64; + + let fixed_native_mint_transaction = + TransactionV1Builder::new_transfer(amount, None, target_public_key, None) + .expect("must get builder") + .with_chain_name(chain_name) + .with_secret_key(&alice_secret_key) + .with_pricing_mode(PricingMode::Fixed { + gas_price_tolerance: max_gas_price, + }) + .build() + .expect("must get transaction"); + + let txn = Transaction::V1(fixed_native_mint_transaction); + let txn_hash = txn.hash(); + + fixture.inject_transaction(txn).await; + fixture + .run_until_executed_transaction(&txn_hash, TEN_SECS) + .await; + + let holds_after = fixture.check_account_balance_hold_at_tip(alice_public_key.clone()); + + let current_gas_price = fixture + .highest_complete_block() + .maybe_current_gas_price() + .expect("must have gas price"); + let cost = + fixture.chainspec.system_costs_config.mint_costs().transfer * (current_gas_price as u32); + assert_eq!(holds_after, holds_before + U512::from(cost)); // Run the network at zero load and ensure the value falls back to the floor. for _ in 0..5 { diff --git a/node/src/reactor/main_reactor/tests/binary_port.rs b/node/src/reactor/main_reactor/tests/binary_port.rs index 9124490693..127cd16f91 100644 --- a/node/src/reactor/main_reactor/tests/binary_port.rs +++ b/node/src/reactor/main_reactor/tests/binary_port.rs @@ -6,17 +6,17 @@ use std::{ time::Duration, }; +use casper_binary_port::{ + BinaryRequest, BinaryRequestHeader, BinaryResponse, BinaryResponseAndRequest, ConsensusStatus, + ConsensusValidatorChanges, DictionaryItemIdentifier, DictionaryQueryResult, ErrorCode, + GetRequest, GetTrieFullResult, GlobalStateQueryResult, GlobalStateRequest, InformationRequest, + InformationRequestTag, LastProgress, NetworkName, NodeStatus, PayloadType, ReactorStateName, + RecordId, Uptime, +}; use casper_storage::global_state::state::CommitProvider; use casper_types::{ account::{AccountHash, ActionThresholds, AssociatedKeys}, addressable_entity::{NamedKeyAddr, NamedKeyValue}, - binary_port::{ - BinaryRequest, BinaryRequestHeader, BinaryResponse, BinaryResponseAndRequest, - ConsensusStatus, ConsensusValidatorChanges, DictionaryItemIdentifier, - DictionaryQueryResult, ErrorCode, GetRequest, GetTrieFullResult, GlobalStateQueryResult, - GlobalStateRequest, InformationRequest, InformationRequestTag, LastProgress, NetworkName, - NodeStatus, PayloadType, ReactorStateName, RecordId, Uptime, - }, bytesrepr::{FromBytes, ToBytes}, execution::{Effects, TransformKindV2, TransformV2}, testing::TestRng, @@ -348,7 +348,7 @@ async fn binary_port_component() { TEST_DICT_NAME.to_owned(), TEST_DICT_ITEM_KEY.to_owned(), ), - try_spec_exec_invalid(&mut rng, highest_block.clone_header()), + try_spec_exec_invalid(&mut rng), try_accept_transaction_invalid(&mut rng), try_accept_transaction(&secret_signing_key), ]; @@ -862,17 +862,11 @@ fn try_accept_transaction_invalid(rng: &mut TestRng) -> TestCase { } } -fn try_spec_exec_invalid(rng: &mut TestRng, header: BlockHeader) -> TestCase { +fn try_spec_exec_invalid(rng: &mut TestRng) -> TestCase { let transaction = Transaction::V1(TransactionV1Builder::new_random(rng).build().unwrap()); TestCase { name: "try_spec_exec_invalid", - request: BinaryRequest::TrySpeculativeExec { - state_root_hash: *header.state_root_hash(), - block_time: header.timestamp(), - protocol_version: header.protocol_version(), - transaction, - speculative_exec_at_block: header, - }, + request: BinaryRequest::TrySpeculativeExec { transaction }, asserter: Box::new(|response| response.error_code() == ErrorCode::InvalidTransaction as u8), } } diff --git a/node/src/reactor/main_reactor/tests/transactions.rs b/node/src/reactor/main_reactor/tests/transactions.rs new file mode 100644 index 0000000000..89b9c53cd5 --- /dev/null +++ b/node/src/reactor/main_reactor/tests/transactions.rs @@ -0,0 +1,805 @@ +use super::*; + +use casper_types::execution::ExecutionResultV1; + +async fn transfer_to_account>( + fixture: &mut TestFixture, + amount: A, + from: &SecretKey, + to: PublicKey, + pricing: PricingMode, + transfer_id: Option, +) -> (TransactionHash, u64, ExecutionResult) { + let chain_name = fixture.chainspec.network_config.name.clone(); + + let mut txn = Transaction::from( + TransactionV1Builder::new_transfer(amount, None, to, transfer_id) + .unwrap() + .with_initiator_addr(PublicKey::from(from)) + .with_pricing_mode(pricing) + .with_chain_name(chain_name) + .build() + .unwrap(), + ); + + txn.sign(from); + let txn_hash = txn.hash(); + + fixture.inject_transaction(txn).await; + fixture + .run_until_executed_transaction(&txn_hash, TEN_SECS) + .await; + + let (_node_id, runner) = fixture.network.nodes().iter().next().unwrap(); + let exec_info = runner + .main_reactor() + .storage() + .read_execution_info(txn_hash) + .expect("Expected transaction to be included in a block."); + + ( + txn_hash, + exec_info.block_height, + exec_info + .execution_result + .expect("Exec result should have been stored."), + ) +} + +fn get_balance( + fixture: &mut TestFixture, + account_key: &PublicKey, + block_height: Option, + get_total: bool, +) -> BalanceResult { + let (_node_id, runner) = fixture.network.nodes().iter().next().unwrap(); + let protocol_version = fixture.chainspec.protocol_version(); + let block_height = block_height.unwrap_or( + runner + .main_reactor() + .storage() + .highest_complete_block_height() + .expect("missing highest completed block"), + ); + let block_header = runner + .main_reactor() + .storage() + .read_block_header_by_height(block_height, true) + .expect("failure to read block header") + .unwrap(); + let state_hash = *block_header.state_root_hash(); + let balance_handling = if get_total { + BalanceHandling::Total + } else { + let block_time = block_header.timestamp().into(); + BalanceHandling::Available { + holds_epoch: HoldsEpoch::from_block_time( + block_time, + fixture.chainspec.core_config.balance_hold_interval, + ), + } + }; + runner + .main_reactor() + .contract_runtime() + .data_access_layer() + .balance(BalanceRequest::from_public_key( + state_hash, + protocol_version, + account_key.clone(), + balance_handling, + )) +} + +#[allow(unused)] +fn get_entity(fixture: &mut TestFixture, account_key: PublicKey) -> AddressableEntityResult { + let (_node_id, runner) = fixture.network.nodes().iter().next().unwrap(); + let highest_completed_height = runner + .main_reactor() + .storage() + .highest_complete_block_height() + .expect("missing highest completed block"); + let state_hash = *runner + .main_reactor() + .storage() + .read_block_header_by_height(highest_completed_height, true) + .expect("failure to read block header") + .unwrap() + .state_root_hash(); + runner + .main_reactor() + .contract_runtime() + .data_access_layer() + .addressable_entity(AddressableEntityRequest::new( + state_hash, + AccountHash::from_public_key(&account_key, crypto::blake2b).into(), + )) +} + +fn get_total_supply(fixture: &mut TestFixture, block_height: Option) -> U512 { + let (_node_id, runner) = fixture.network.nodes().iter().next().unwrap(); + let protocol_version = fixture.chainspec.protocol_version(); + let height = block_height.unwrap_or( + runner + .main_reactor() + .storage() + .highest_complete_block_height() + .expect("missing highest completed block"), + ); + let state_hash = *runner + .main_reactor() + .storage() + .read_block_header_by_height(height, true) + .expect("failure to read block header") + .unwrap() + .state_root_hash(); + + let total_supply_req = TotalSupplyRequest::new(state_hash, protocol_version); + let result = runner + .main_reactor() + .contract_runtime() + .data_access_layer() + .total_supply(total_supply_req); + + if let TotalSupplyResult::Success { total_supply } = result { + total_supply + } else { + panic!("Can't get total supply") + } +} + +fn assert_exec_result_cost( + exec_result: ExecutionResult, + expected_cost: U512, + expected_consumed_gas: Gas, +) { + match exec_result { + ExecutionResult::V2(exec_result_v2) => { + assert_eq!(exec_result_v2.cost, expected_cost); + assert_eq!(exec_result_v2.consumed, expected_consumed_gas); + } + _ => { + panic!("Unexpected exec result version.") + } + } +} + +// Returns `true` is the execution result is a success. +pub fn exec_result_is_success(exec_result: &ExecutionResult) -> bool { + match exec_result { + ExecutionResult::V2(execution_result_v2) => execution_result_v2.error_message.is_none(), + ExecutionResult::V1(ExecutionResultV1::Success { .. }) => true, + ExecutionResult::V1(ExecutionResultV1::Failure { .. }) => false, + } +} + +#[tokio::test] +async fn transfer_cost_fixed_price_no_fee_no_refund() { + const TRANSFER_AMOUNT: u64 = 30_000_000_000; + + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + let config = ConfigsOverride::default() + .with_pricing_handling(PricingHandling::Fixed) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::NoFee) + .with_balance_hold_interval(TimeDiff::from_seconds(5)); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let alice_public_key = PublicKey::from(&*alice_secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let charlie_public_key = PublicKey::from(&*charlie_secret_key); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let alice_initial_balance = *get_balance(&mut fixture, &alice_public_key, None, true) + .motes() + .expect("Expected Alice to have a balance."); + + let (_txn_hash, block_height, exec_result) = transfer_to_account( + &mut fixture, + TRANSFER_AMOUNT, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Fixed { + gas_price_tolerance: 1, + }, + Some(0xDEADBEEF), + ) + .await; + + let expected_transfer_gas = fixture + .chainspec + .system_costs_config + .mint_costs() + .transfer + .into(); + let expected_transfer_cost = expected_transfer_gas; // since we set gas_price_tolerance to 1. + + assert_exec_result_cost( + exec_result, + expected_transfer_cost, + Gas::new(expected_transfer_gas), + ); + + let alice_available_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), false); + let alice_total_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), true); + + // since FeeHandling is set to NoFee, we expect that there's a hold on Alice's balance for the + // cost of the transfer. The total balance of Alice now should be the initial balance - the + // amount transfered to Charlie. + let alice_expected_total_balance = alice_initial_balance - TRANSFER_AMOUNT; + // The available balance is the initial balance - the amount transferred to Charlie - the hold + // for the transfer cost. + let alice_expected_available_balance = alice_expected_total_balance - expected_transfer_cost; + + assert_eq!( + alice_total_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_total_balance + ); + assert_eq!( + alice_available_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_available_balance + ); + + let charlie_balance = get_balance(&mut fixture, &charlie_public_key, Some(block_height), false); + assert_eq!( + charlie_balance + .motes() + .expect("Expected Charlie to have a balance") + .clone(), + TRANSFER_AMOUNT.into() + ); + + // Check if the hold is released. + let hold_release_block_height = block_height + 8; // Block time is 1s. + fixture + .run_until_block_height(hold_release_block_height, ONE_MIN) + .await; + + let alice_available_balance = get_balance( + &mut fixture, + &alice_public_key, + Some(hold_release_block_height), + false, + ); + let alice_total_balance = get_balance( + &mut fixture, + &alice_public_key, + Some(hold_release_block_height), + true, + ); + + assert_eq!(alice_available_balance.motes(), alice_total_balance.motes()); +} + +#[tokio::test] +async fn should_accept_transfer_without_id() { + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + let config = ConfigsOverride::default().with_pricing_handling(PricingHandling::Fixed); + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + let transfer_amount = fixture + .chainspec + .transaction_config + .native_transfer_minimum_motes + + 100; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let (_, _, result) = transfer_to_account( + &mut fixture, + transfer_amount, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Fixed { + gas_price_tolerance: 1, + }, + None, + ) + .await; + + assert!(exec_result_is_success(&result)) +} + +#[tokio::test] +async fn failed_transfer_cost_fixed_price_no_fee_no_refund() { + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + let config = ConfigsOverride::default() + .with_pricing_handling(PricingHandling::Fixed) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::NoFee) + .with_balance_hold_interval(TimeDiff::from_seconds(5)); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let charlie_public_key = PublicKey::from(&*charlie_secret_key); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let transfer_amount = fixture + .chainspec + .transaction_config + .native_transfer_minimum_motes + + 100; + + // Transfer some token to Charlie. + let (_txn_hash, _block, exec_result) = transfer_to_account( + &mut fixture, + transfer_amount, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Fixed { + gas_price_tolerance: 1, + }, + None, + ) + .await; + assert!(exec_result_is_success(&exec_result)); + + // Attempt to transfer more than Charlie has to Bob. + let bob_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let (_txn_hash, block_height, exec_result) = transfer_to_account( + &mut fixture, + transfer_amount + 100, + &charlie_secret_key, + PublicKey::from(&*bob_secret_key), + PricingMode::Fixed { + gas_price_tolerance: 1, + }, + None, + ) + .await; + assert!(!exec_result_is_success(&exec_result)); // transaction should have failed. + + let expected_transfer_gas = fixture + .chainspec + .system_costs_config + .mint_costs() + .transfer + .into(); + let expected_transfer_cost = expected_transfer_gas; // since we set gas_price_tolerance to 1. + + assert_exec_result_cost( + exec_result, + expected_transfer_cost, + Gas::new(expected_transfer_gas), + ); + + // Even though the transaction failed, a hold must still be in place for the transfer cost. + let charlie_available_balance = + get_balance(&mut fixture, &charlie_public_key, Some(block_height), false); + assert_eq!( + charlie_available_balance + .motes() + .expect("Expected Charlie to have a balance") + .clone(), + U512::from(transfer_amount) - expected_transfer_cost + ); +} + +#[tokio::test] +async fn transfer_cost_classic_price_no_fee_no_refund() { + const TRANSFER_AMOUNT: u64 = 30_000_000_000; + const MIN_GAS_PRICE: u8 = 5; + const MAX_GAS_PRICE: u8 = MIN_GAS_PRICE * 2; + + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + let config = ConfigsOverride::default() + .with_pricing_handling(PricingHandling::Classic) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::NoFee) + .with_balance_hold_interval(TimeDiff::from_seconds(5)) + .with_min_gas_price(MIN_GAS_PRICE) + .with_max_gas_price(MAX_GAS_PRICE); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let alice_public_key = PublicKey::from(&*alice_secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let charlie_public_key = PublicKey::from(&*charlie_secret_key); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let alice_initial_balance = *get_balance(&mut fixture, &alice_public_key, None, true) + .motes() + .expect("Expected Alice to have a balance."); + + const TRANSFER_GAS: u64 = 100; + + // This transaction should be included since the tolerance is above the min gas price. + let (_txn_hash, block_height, exec_result) = transfer_to_account( + &mut fixture, + TRANSFER_AMOUNT, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Classic { + payment_amount: TRANSFER_GAS, + gas_price_tolerance: MIN_GAS_PRICE + 1, + standard_payment: true, + }, + None, + ) + .await; + + let expected_transfer_cost = TRANSFER_GAS * MIN_GAS_PRICE as u64; + + assert!(exec_result_is_success(&exec_result)); // transaction should have succeeded. + assert_exec_result_cost( + exec_result, + expected_transfer_cost.into(), + Gas::new(TRANSFER_GAS), + ); + + let alice_available_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), false); + let alice_total_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), true); + + // since FeeHandling is set to NoFee, we expect that there's a hold on Alice's balance for the + // cost of the transfer. The total balance of Alice now should be the initial balance - the + // amount transfered to Charlie. + let alice_expected_total_balance = alice_initial_balance - TRANSFER_AMOUNT; + // The available balance is the initial balance - the amount transferred to Charlie - the hold + // for the transfer cost. + let alice_expected_available_balance = alice_expected_total_balance - expected_transfer_cost; + + assert_eq!( + alice_total_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_total_balance + ); + assert_eq!( + alice_available_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_available_balance + ); + + let charlie_balance = get_balance(&mut fixture, &charlie_public_key, Some(block_height), false); + assert_eq!( + charlie_balance + .motes() + .expect("Expected Charlie to have a balance") + .clone(), + TRANSFER_AMOUNT.into() + ); + + // Check if the hold is released. + let hold_release_block_height = block_height + 8; // Block time is 1s. + fixture + .run_until_block_height(hold_release_block_height, ONE_MIN) + .await; + + let alice_available_balance = get_balance( + &mut fixture, + &alice_public_key, + Some(hold_release_block_height), + false, + ); + let alice_total_balance = get_balance( + &mut fixture, + &alice_public_key, + Some(hold_release_block_height), + true, + ); + + assert_eq!(alice_available_balance.motes(), alice_total_balance.motes()); +} + +#[tokio::test] +#[should_panic = "within 10 seconds"] +async fn transaction_with_low_threshold_should_not_get_included() { + const TRANSFER_AMOUNT: u64 = 30_000_000_000; + const MIN_GAS_PRICE: u8 = 5; + const MAX_GAS_PRICE: u8 = MIN_GAS_PRICE * 2; + + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + let config = ConfigsOverride::default() + .with_pricing_handling(PricingHandling::Classic) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::NoFee) + .with_balance_hold_interval(TimeDiff::from_seconds(5)) + .with_min_gas_price(MIN_GAS_PRICE) + .with_max_gas_price(MAX_GAS_PRICE); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + // This transaction should NOT be included since the tolerance is below the min gas price. + let (_, _, _) = transfer_to_account( + &mut fixture, + TRANSFER_AMOUNT, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Classic { + payment_amount: 1000, + gas_price_tolerance: MIN_GAS_PRICE - 1, + standard_payment: true, + }, + None, + ) + .await; +} + +#[tokio::test] +async fn transfer_fee_is_burnt_no_refund() { + const MIN_GAS_PRICE: u8 = 5; + const MAX_GAS_PRICE: u8 = MIN_GAS_PRICE; + + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); + + // make the era longer so that the transaction doesn't land in the switch block. + let minimum_era_height = 5; + // make the hold interval very short so we can see the behavior. + let balance_hold_interval = TimeDiff::from_seconds(5); + + let config = ConfigsOverride::default() + .with_minimum_era_height(minimum_era_height) + .with_pricing_handling(PricingHandling::Fixed) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::Burn) + .with_balance_hold_interval(balance_hold_interval) + .with_min_gas_price(MIN_GAS_PRICE) + .with_max_gas_price(MAX_GAS_PRICE); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let alice_public_key = PublicKey::from(&*alice_secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let charlie_public_key = PublicKey::from(&*charlie_secret_key); + + info!("waiting for all nodes to complete era 0"); + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let initial_total_supply = get_total_supply(&mut fixture, None); + + let alice_initial_balance = *get_balance(&mut fixture, &alice_public_key, None, true) + .motes() + .expect("expected alice to have a balance"); + + let transfer_amount = fixture + .chainspec + .transaction_config + .native_transfer_minimum_motes + + 100; + + info!("transferring from alice to charlie"); + let (_txn_hash, block_height, exec_result) = transfer_to_account( + &mut fixture, + transfer_amount, + &alice_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Fixed { + gas_price_tolerance: MIN_GAS_PRICE, + }, + None, + ) + .await; + assert!(exec_result_is_success(&exec_result), "{:?}", exec_result); + info!("transfer was successful"); + + let expected_transfer_gas: u64 = fixture + .chainspec + .system_costs_config + .mint_costs() + .transfer + .into(); + let expected_transfer_cost = expected_transfer_gas * MIN_GAS_PRICE as u64; + info!("checking expected cost"); + assert_exec_result_cost( + exec_result, + expected_transfer_cost.into(), + expected_transfer_gas.into(), + ); + + // The fees should have been burnt so expect the total supply to have been + // reduced by the fee that was burnt. + info!("checking total supply"); + let total_supply_after_transaction = get_total_supply(&mut fixture, Some(block_height)); + assert_ne!( + total_supply_after_transaction, initial_total_supply, + "total supply should be lowered" + ); + let diff = initial_total_supply - total_supply_after_transaction; + assert_eq!( + diff, + U512::from(expected_transfer_cost), + "total supply should be lowered by expected transfer cost" + ); + + let alice_available_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), false); + let alice_total_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), true); + let alice_expected_total_balance = + alice_initial_balance - transfer_amount - expected_transfer_cost; + let alice_expected_available_balance = alice_expected_total_balance; + + info!("checking charlie balance"); + let charlie_balance = get_balance(&mut fixture, &charlie_public_key, Some(block_height), false); + assert_eq!( + charlie_balance + .motes() + .expect("Expected Charlie to have a balance") + .clone(), + transfer_amount.into() + ); + + info!("checking alice available balance"); + assert_eq!( + alice_available_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_available_balance + ); + + info!("checking alice total balance"); + assert_eq!( + alice_total_balance + .motes() + .expect("Expected Alice to have a balance") + .clone(), + alice_expected_total_balance + ); +} + +#[tokio::test] +async fn fee_is_payed_to_proposer_no_refund() { + const MIN_GAS_PRICE: u8 = 5; + const MAX_GAS_PRICE: u8 = MIN_GAS_PRICE; + + let initial_stakes = InitialStakes::FromVec(vec![u128::MAX, 1]); // Node 0 is effectively guaranteed to be the proposer. + + let config = ConfigsOverride::default() + .with_minimum_era_height(5) // make the era longer so that the transaction doesn't land in the switch block. + .with_pricing_handling(PricingHandling::Fixed) + .with_refund_handling(RefundHandling::NoRefund) + .with_fee_handling(FeeHandling::PayToProposer) + .with_balance_hold_interval(TimeDiff::from_seconds(5)) + .with_min_gas_price(MIN_GAS_PRICE) + .with_max_gas_price(MAX_GAS_PRICE); + + let mut fixture = TestFixture::new(initial_stakes, Some(config)).await; + + let alice_secret_key = Arc::clone(&fixture.node_contexts[0].secret_key); + let alice_public_key = PublicKey::from(&*alice_secret_key); + let bob_secret_key = Arc::clone(&fixture.node_contexts[1].secret_key); + let bob_public_key = PublicKey::from(&*bob_secret_key); + let charlie_secret_key = Arc::new(SecretKey::random(&mut fixture.rng)); + let charlie_public_key = PublicKey::from(&*charlie_secret_key); + + // Wait for all nodes to complete era 0. + fixture.run_until_consensus_in_era(ERA_ONE, ONE_MIN).await; + + let bob_initial_balance = *get_balance(&mut fixture, &bob_public_key, None, true) + .motes() + .expect("Expected Bob to have a balance."); + let alice_initial_balance = *get_balance(&mut fixture, &alice_public_key, None, true) + .motes() + .expect("Expected Alice to have a balance."); + + let transfer_amount = fixture + .chainspec + .transaction_config + .native_transfer_minimum_motes + + 100; + + let (_txn_hash, block_height, exec_result) = transfer_to_account( + &mut fixture, + transfer_amount, + &bob_secret_key, + PublicKey::from(&*charlie_secret_key), + PricingMode::Fixed { + gas_price_tolerance: MIN_GAS_PRICE, + }, + None, + ) + .await; + + assert!(exec_result_is_success(&exec_result)); // transaction should have succeeded. + + let expected_transfer_gas: u64 = fixture + .chainspec + .system_costs_config + .mint_costs() + .transfer + .into(); + let expected_transfer_cost = expected_transfer_gas * MIN_GAS_PRICE as u64; + assert_exec_result_cost( + exec_result, + expected_transfer_cost.into(), + expected_transfer_gas.into(), + ); + + let bob_available_balance = + get_balance(&mut fixture, &bob_public_key, Some(block_height), false); + let bob_total_balance = get_balance(&mut fixture, &bob_public_key, Some(block_height), true); + + let alice_available_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), false); + let alice_total_balance = + get_balance(&mut fixture, &alice_public_key, Some(block_height), true); + + // since Alice was the proposer of the block, it should get back the transfer fee since + // FeeHandling is set to PayToProposer. + let bob_expected_total_balance = bob_initial_balance - transfer_amount - expected_transfer_cost; + let bob_expected_available_balance = bob_expected_total_balance; + + let alice_expected_total_balance = alice_initial_balance + expected_transfer_cost; + let alice_expected_available_balance = alice_expected_total_balance; + + let charlie_balance = get_balance(&mut fixture, &charlie_public_key, Some(block_height), false); + assert_eq!( + charlie_balance + .motes() + .expect("Expected Charlie to have a balance") + .clone(), + transfer_amount.into() + ); + + assert_eq!( + bob_available_balance + .motes() + .expect("Expected Bob to have a balance") + .clone(), + bob_expected_available_balance + ); + + assert_eq!( + bob_total_balance + .motes() + .expect("Expected Bob to have a balance") + .clone(), + bob_expected_total_balance + ); + + assert_eq!( + alice_available_balance + .motes() + .expect("Expected Bob to have a balance") + .clone(), + alice_expected_available_balance + ); + + assert_eq!( + alice_total_balance + .motes() + .expect("Expected Bob to have a balance") + .clone(), + alice_expected_total_balance + ); +} diff --git a/node/src/types.rs b/node/src/types.rs index 4f1b71d939..95a836b2c0 100644 --- a/node/src/types.rs +++ b/node/src/types.rs @@ -36,7 +36,7 @@ pub use node_config::{NodeConfig, SyncHandling}; pub(crate) use node_id::NodeId; pub use status_feed::{ChainspecInfo, GetStatusResult, StatusFeed}; pub(crate) use sync_leap::{GlobalStatesMetadata, SyncLeap, SyncLeapIdentifier}; -pub(crate) use transaction::{LegacyDeploy, TransactionExt, TransactionFootprint}; +pub(crate) use transaction::{LegacyDeploy, TransactionFootprint}; pub(crate) use validator_matrix::{EraValidatorWeights, SignatureWeight, ValidatorMatrix}; pub use value_or_chunk::{ ChunkingError, TrieOrChunk, TrieOrChunkId, TrieOrChunkIdDisplay, ValueOrChunk, diff --git a/node/src/types/block/block_execution_results_or_chunk.rs b/node/src/types/block/block_execution_results_or_chunk.rs index bb0a2f8e64..6d8114a79c 100644 --- a/node/src/types/block/block_execution_results_or_chunk.rs +++ b/node/src/types/block/block_execution_results_or_chunk.rs @@ -2,8 +2,6 @@ use std::fmt::{self, Debug, Display, Formatter}; use datasize::DataSize; use once_cell::sync::OnceCell; -#[cfg(test)] -use rand::Rng; use serde::{Deserialize, Serialize}; use tracing::{debug, error}; @@ -181,7 +179,7 @@ impl BlockExecutionResultsOrChunk { ) -> Self { let execution_results: Vec = (0..num_results) .into_iter() - .map(|_| rng.gen::().into()) + .map(|_| ExecutionResultV2::random(rng).into()) .collect(); Self { diff --git a/node/src/types/block/executable_block.rs b/node/src/types/block/executable_block.rs index ded26c6c43..5272304c8f 100644 --- a/node/src/types/block/executable_block.rs +++ b/node/src/types/block/executable_block.rs @@ -73,8 +73,8 @@ impl ExecutableBlock { height: block.height(), proposer: Box::new(block.proposer().clone()), transactions, - mint: block.transfer().copied().collect(), - auction: block.staking().copied().collect(), + mint: block.mint().copied().collect(), + auction: block.auction().copied().collect(), install_upgrade: block.install_upgrade().copied().collect(), standard: block.standard().copied().collect(), rewards: block.era_end().map(|era_end| era_end.rewards().clone()), diff --git a/node/src/types/block/finalized_block.rs b/node/src/types/block/finalized_block.rs index b917fd000b..0cbef73e3e 100644 --- a/node/src/types/block/finalized_block.rs +++ b/node/src/types/block/finalized_block.rs @@ -149,8 +149,8 @@ impl FinalizedBlock { impl From for FinalizedBlock { fn from(block: BlockV2) -> Self { FinalizedBlock { - mint: block.transfer().copied().collect(), - auction: block.staking().copied().collect(), + mint: block.mint().copied().collect(), + auction: block.auction().copied().collect(), install_upgrade: block.install_upgrade().copied().collect(), standard: block.standard().copied().collect(), timestamp: block.timestamp(), diff --git a/node/src/types/block/meta_block.rs b/node/src/types/block/meta_block.rs index 63ac6f7c0d..93b38957bd 100644 --- a/node/src/types/block/meta_block.rs +++ b/node/src/types/block/meta_block.rs @@ -171,7 +171,9 @@ impl From for MetaBlock { mod tests { use std::convert::TryInto; - use casper_types::{execution::ExecutionResultV2, testing::TestRng, Deploy, TestBlockBuilder}; + use casper_types::{ + execution::ExecutionResultV2, testing::TestRng, TestBlockBuilder, TransactionV1, + }; use super::*; @@ -180,10 +182,10 @@ mod tests { let rng = &mut TestRng::new(); let block = Arc::new(TestBlockBuilder::new().build(rng)); - let deploy = Deploy::random(rng); - let execution_results = vec![ExecutionArtifact::deploy( - *deploy.hash(), - deploy.take_header(), + let txn = TransactionV1::random(rng); + let execution_results = vec![ExecutionArtifact::new( + TransactionHash::V1(*txn.hash()), + TransactionHeader::V1(txn.take_header()), ExecutionResult::from(ExecutionResultV2::random(rng)), Vec::new(), )]; @@ -235,10 +237,10 @@ mod tests { let rng = &mut TestRng::new(); let block = Arc::new(TestBlockBuilder::new().build(rng)); - let deploy = Deploy::random(rng); - let execution_results = vec![ExecutionArtifact::deploy( - *deploy.hash(), - deploy.take_header(), + let txn = TransactionV1::random(rng); + let execution_results = vec![ExecutionArtifact::new( + TransactionHash::V1(*txn.hash()), + TransactionHeader::V1(txn.take_header()), ExecutionResult::from(ExecutionResultV2::random(rng)), Vec::new(), )]; @@ -273,10 +275,10 @@ mod tests { .switch_block(true) .build(rng), ); - let deploy = Deploy::random(rng); - let execution_results = vec![ExecutionArtifact::deploy( - *deploy.hash(), - deploy.take_header(), + let txn = TransactionV1::random(rng); + let execution_results = vec![ExecutionArtifact::new( + TransactionHash::V1(*txn.hash()), + TransactionHeader::V1(txn.take_header()), ExecutionResult::from(ExecutionResultV2::random(rng)), Vec::new(), )]; @@ -306,17 +308,17 @@ mod tests { let rng = &mut TestRng::new(); let block = Arc::new(TestBlockBuilder::new().build(rng)); - let deploy1 = Deploy::random(rng); - let execution_results1 = vec![ExecutionArtifact::deploy( - *deploy1.hash(), - deploy1.take_header(), + let txn1 = TransactionV1::random(rng); + let execution_results1 = vec![ExecutionArtifact::new( + TransactionHash::V1(*txn1.hash()), + TransactionHeader::V1(txn1.take_header()), ExecutionResult::from(ExecutionResultV2::random(rng)), Vec::new(), )]; - let deploy2 = Deploy::random(rng); - let execution_results2 = vec![ExecutionArtifact::deploy( - *deploy2.hash(), - deploy2.take_header(), + let txn2 = TransactionV1::random(rng); + let execution_results2 = vec![ExecutionArtifact::new( + TransactionHash::V1(*txn2.hash()), + TransactionHeader::V1(txn2.take_header()), ExecutionResult::from(ExecutionResultV2::random(rng)), Vec::new(), )]; diff --git a/node/src/types/json_compatibility/addressable_entity.rs b/node/src/types/json_compatibility/addressable_entity.rs deleted file mode 100644 index 3ec488020f..0000000000 --- a/node/src/types/json_compatibility/addressable_entity.rs +++ /dev/null @@ -1,72 +0,0 @@ -// TODO - remove once schemars stops causing warning. -#![allow(clippy::field_reassign_with_default)] - -use datasize::DataSize; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use crate::types::json_compatibility::vectorize; -use casper_types::{ - account::AccountHash, addressable_entity::AddressableEntity as DomainEntity, - ContractPackageHash, ContractWasmHash, EntryPoint, NamedKey, ProtocolVersion, URef, -}; - -#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, DataSize, JsonSchema)] -#[serde(deny_unknown_fields)] -struct AssociatedKey { - account_hash: AccountHash, - weight: u8, -} - -/// Thresholds that have to be met when executing an action of a certain type. -#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, DataSize, JsonSchema)] -#[serde(deny_unknown_fields)] -struct ActionThresholds { - deployment: u8, - key_management: u8, -} - -/// A contract struct that can be serialized as JSON object. -#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, DataSize, JsonSchema)] -#[serde(deny_unknown_fields)] -pub struct AddressableEntity { - contract_package_hash: ContractPackageHash, - contract_wasm_hash: ContractWasmHash, - #[data_size(skip)] - named_keys: Vec, - #[data_size(skip)] - entry_points: Vec, - #[data_size(skip)] - #[schemars(with = "String")] - protocol_version: ProtocolVersion, - #[data_size(skip)] - main_purse: URef, - associated_keys: Vec, - action_thresholds: ActionThresholds, -} - -impl From<&DomainEntity> for AddressableEntity { - fn from(entity: &DomainEntity) -> Self { - let entry_points = entity.entry_points().clone().take_entry_points(); - Self { - contract_package_hash: entity.contract_package_hash(), - contract_wasm_hash: entity.contract_wasm_hash(), - named_keys: vectorize(entity.named_keys()), - entry_points, - protocol_version: entity.protocol_version(), - main_purse: entity.main_purse(), - associated_keys: entity - .associated_keys() - .iter() - .map(|(account_hash, weight)| AssociatedKey { - account_hash: *account_hash, - weight: weight.value(), - }) - .collect(), - action_thresholds: ActionThresholds { - deployment: entity.action_thresholds().deployment().value(), - key_management: entity.action_thresholds().key_management().value(), - }, - } - } -} diff --git a/node/src/types/status_feed.rs b/node/src/types/status_feed.rs index 8f4eb55794..f90160b2d8 100644 --- a/node/src/types/status_feed.rs +++ b/node/src/types/status_feed.rs @@ -8,10 +8,10 @@ use once_cell::sync::Lazy; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use casper_binary_port::ConsensusStatus; use casper_types::{ - binary_port::ConsensusStatus, ActivationPoint, AvailableBlockRange, Block, BlockHash, - BlockSynchronizerStatus, Digest, EraId, NextUpgrade, Peers, ProtocolVersion, PublicKey, - TimeDiff, Timestamp, + ActivationPoint, AvailableBlockRange, Block, BlockHash, BlockSynchronizerStatus, Digest, EraId, + NextUpgrade, Peers, ProtocolVersion, PublicKey, TimeDiff, Timestamp, }; use crate::{ diff --git a/node/src/types/transaction.rs b/node/src/types/transaction.rs index 5ae855dafe..3fa0faaa3b 100644 --- a/node/src/types/transaction.rs +++ b/node/src/types/transaction.rs @@ -2,4 +2,4 @@ mod deploy; mod transaction_footprint; pub(crate) use deploy::LegacyDeploy; -pub(crate) use transaction_footprint::{TransactionExt, TransactionFootprint}; +pub(crate) use transaction_footprint::TransactionFootprint; diff --git a/node/src/types/transaction/deploy/legacy_deploy.rs b/node/src/types/transaction/deploy/legacy_deploy.rs index ad2afe97f9..90adc1086c 100644 --- a/node/src/types/transaction/deploy/legacy_deploy.rs +++ b/node/src/types/transaction/deploy/legacy_deploy.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use casper_types::{ bytesrepr::{self, FromBytes, ToBytes}, - Deploy, DeployConfigFailure, DeployHash, Transaction, + Deploy, DeployHash, InvalidDeploy, Transaction, }; use crate::components::fetcher::{EmptyValidationMetadata, FetchItem, Tag}; @@ -15,7 +15,7 @@ pub(crate) struct LegacyDeploy(Deploy); impl FetchItem for LegacyDeploy { type Id = DeployHash; - type ValidationError = DeployConfigFailure; + type ValidationError = InvalidDeploy; type ValidationMetadata = EmptyValidationMetadata; const TAG: Tag = Tag::LegacyDeploy; diff --git a/node/src/types/transaction/transaction_footprint.rs b/node/src/types/transaction/transaction_footprint.rs index 48a5953ea3..a7e5bfde4b 100644 --- a/node/src/types/transaction/transaction_footprint.rs +++ b/node/src/types/transaction/transaction_footprint.rs @@ -1,11 +1,10 @@ use casper_types::{ - bytesrepr::ToBytes, Approval, Chainspec, Digest, Gas, TimeDiff, Timestamp, Transaction, - TransactionCategory, TransactionHash, + Approval, CategorizedTransaction, Chainspec, Digest, Gas, GasLimited, InvalidTransaction, + TimeDiff, Timestamp, Transaction, TransactionCategory, TransactionHash, }; use datasize::DataSize; use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; -use tracing::error; #[derive(Clone, Debug, DataSize, Eq, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -18,7 +17,7 @@ pub(crate) struct TransactionFootprint { /// The estimated gas consumption. pub(crate) gas_limit: Gas, /// The gas tolerance. - pub(crate) gas_tolerance: u64, + pub(crate) gas_price_tolerance: u8, /// The bytesrepr serialized length. pub(crate) size_estimate: usize, /// The transaction category. @@ -32,6 +31,32 @@ pub(crate) struct TransactionFootprint { } impl TransactionFootprint { + pub(crate) fn new( + chainspec: &Chainspec, + transaction: &Transaction, + ) -> Result { + let gas_price_tolerance = transaction.gas_price_tolerance()?; + let gas_limit = transaction.gas_limit(chainspec)?; + let category = transaction.category(); + let transaction_hash = transaction.hash(); + let body_hash = transaction.body_hash(); + let size_estimate = transaction.size_estimate(); + let timestamp = transaction.timestamp(); + let ttl = transaction.ttl(); + let approvals = transaction.approvals(); + Ok(TransactionFootprint { + transaction_hash, + body_hash, + gas_limit, + gas_price_tolerance, + size_estimate, + category, + timestamp, + ttl, + approvals, + }) + } + /// Sets approvals. pub(crate) fn with_approvals(mut self, approvals: BTreeSet) -> Self { self.approvals = approvals; @@ -63,116 +88,7 @@ impl TransactionFootprint { matches!(self.category, TransactionCategory::InstallUpgrade) } - pub(crate) fn gas_tolerance(&self) -> u64 { - self.gas_tolerance - } -} - -pub(crate) trait TransactionExt { - fn footprint(&self, chainspec: &Chainspec) -> Option; -} - -impl TransactionExt for Transaction { - /// Returns the `TransactionFootprint`, if able. - fn footprint(&self, chainspec: &Chainspec) -> Option { - let cost_table = &chainspec.system_costs_config; - - // IMPORTANT: block inclusion is always calculated based upon gas price multiple = 1 - // Do not confuse actual cost with retail cost. - let gas_price: Option = None; - let ( - transaction_hash, - body_hash, - gas_limit, - gas_tolerance, - size_estimate, - category, - timestamp, - ttl, - approvals, - ) = match self { - Transaction::Deploy(deploy) => { - let transaction_hash = TransactionHash::Deploy(*deploy.hash()); - let body_hash = *deploy.header().body_hash(); - let gas_limit = match deploy.gas_limit(cost_table, gas_price) { - Ok(amount) => amount, - Err(err) => { - error!("{:?}", err); - return None; - } - }; - let size_estimate = deploy.serialized_length(); - let category = if deploy.is_transfer() { - TransactionCategory::Mint - } else { - TransactionCategory::Standard - }; - let timestamp = deploy.header().timestamp(); - let ttl = deploy.header().ttl(); - let approvals = self.approvals(); - let gas_tolerance = deploy.header().gas_price(); - ( - transaction_hash, - body_hash, - gas_limit, - gas_tolerance, - size_estimate, - category, - timestamp, - ttl, - approvals, - ) - } - Transaction::V1(transaction) => { - let transaction_hash = TransactionHash::V1(*transaction.hash()); - let body_hash = *transaction.header().body_hash(); - let gas_tolernace = transaction.header().gas_tolerance(); - let gas_limit = match transaction.gas_limit(cost_table, gas_price) { - Some(amount) => amount, - None => { - error!( - "failed to determine gas limit for transaction {:?}", - transaction_hash - ); - return None; - } - }; - let size_estimate = transaction.serialized_length(); - let category = if transaction.is_native_mint() { - TransactionCategory::Mint - } else if transaction.is_native_auction() { - TransactionCategory::Auction - } else if transaction.is_install_or_upgrade() { - TransactionCategory::InstallUpgrade - } else { - TransactionCategory::Standard - }; - let timestamp = transaction.header().timestamp(); - let ttl = transaction.header().ttl(); - let approvals = self.approvals(); - ( - transaction_hash, - body_hash, - gas_limit, - gas_tolernace, - size_estimate, - category, - timestamp, - ttl, - approvals, - ) - } - }; - Some(TransactionFootprint { - transaction_hash, - body_hash, - gas_limit, - gas_tolerance, - size_estimate, - category, - timestamp, - ttl, - approvals, - }) + pub(crate) fn gas_price_tolerance(&self) -> u8 { + self.gas_price_tolerance } } diff --git a/node/src/utils.rs b/node/src/utils.rs index 41b6de2e24..42b124cefd 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -38,8 +38,6 @@ use serde::Serialize; use thiserror::Error; use tracing::{error, warn}; -use casper_types::BlockHeader; - use crate::types::NodeId; pub(crate) use block_signatures::{check_sufficient_block_signatures, BlockSignatureError}; pub(crate) use display_error::display_error; @@ -263,7 +261,7 @@ pub(crate) enum Source { /// A client. Client, /// A client via the speculative_exec server. - SpeculativeExec(Box), + SpeculativeExec, /// This node. Ourself, } @@ -272,7 +270,7 @@ impl Source { #[allow(clippy::wrong_self_convention)] pub(crate) fn is_client(&self) -> bool { match self { - Source::Client | Source::SpeculativeExec(_) => true, + Source::Client | Source::SpeculativeExec => true, Source::PeerGossiped(_) | Source::Peer(_) | Source::Ourself => false, } } @@ -281,7 +279,7 @@ impl Source { pub(crate) fn node_id(&self) -> Option { match self { Source::Peer(node_id) | Source::PeerGossiped(node_id) => Some(*node_id), - Source::Client | Source::SpeculativeExec(_) | Source::Ourself => None, + Source::Client | Source::SpeculativeExec | Source::Ourself => None, } } } @@ -292,7 +290,7 @@ impl Display for Source { Source::PeerGossiped(node_id) => Display::fmt(node_id, formatter), Source::Peer(node_id) => Display::fmt(node_id, formatter), Source::Client => write!(formatter, "client"), - Source::SpeculativeExec(_) => write!(formatter, "client (speculative exec)"), + Source::SpeculativeExec => write!(formatter, "client (speculative exec)"), Source::Ourself => write!(formatter, "ourself"), } } diff --git a/node/src/utils/chain_specification.rs b/node/src/utils/chain_specification.rs index cb3b947917..0aab5ab567 100644 --- a/node/src/utils/chain_specification.rs +++ b/node/src/utils/chain_specification.rs @@ -152,7 +152,7 @@ mod tests { bytesrepr::FromBytes, ActivationPoint, BrTableCost, ChainspecRawBytes, ControlFlowCosts, CoreConfig, EraId, GlobalStateUpdate, HighwayConfig, HostFunction, HostFunctionCosts, MessageLimits, Motes, OpcodeCosts, ProtocolConfig, ProtocolVersion, StorageCosts, - StoredValue, TestBlockBuilder, TimeDiff, Timestamp, TransactionConfig, WasmConfig, U512, + StoredValue, TestBlockBuilder, TimeDiff, Timestamp, TransactionConfig, WasmConfig, }; use super::*; @@ -560,10 +560,10 @@ mod tests { }; for (index, account_config) in accounts.into_iter().enumerate() { - assert_eq!(account_config.balance(), Motes::new(U512::from(index + 1)),); + assert_eq!(account_config.balance(), Motes::new(index + 1),); assert_eq!( account_config.bonded_amount(), - Motes::new(U512::from((index as u64 + 1) * 10)) + Motes::new((index as u64 + 1) * 10) ); } } else { @@ -614,7 +614,7 @@ mod tests { assert_eq!( spec.transaction_config.deploy_config.max_payment_cost, - Motes::new(U512::from(9)) + Motes::new(9) ); assert_eq!( spec.transaction_config.max_ttl, diff --git a/node/src/utils/chain_specification/parse_toml.rs b/node/src/utils/chain_specification/parse_toml.rs index a89d531e9d..98ad87fb00 100644 --- a/node/src/utils/chain_specification/parse_toml.rs +++ b/node/src/utils/chain_specification/parse_toml.rs @@ -118,7 +118,8 @@ pub(super) fn parse_toml>( ) -> Result<(Chainspec, ChainspecRawBytes), Error> { let chainspec_bytes = file_utils::read_file(chainspec_path.as_ref()).map_err(Error::LoadChainspec)?; - let toml_chainspec: TomlChainspec = toml::from_slice(&chainspec_bytes)?; + let toml_chainspec: TomlChainspec = + toml::from_str(std::str::from_utf8(&chainspec_bytes).unwrap())?; let root = chainspec_path .as_ref() @@ -193,7 +194,7 @@ pub(super) fn parse_toml_accounts>( return Ok((config, maybe_bytes)); } let bytes = file_utils::read_file(accounts_path)?; - let config: AccountsConfig = toml::from_slice(&bytes)?; + let config: AccountsConfig = toml::from_str(std::str::from_utf8(&bytes).unwrap())?; Ok((config, Some(Bytes::from(bytes)))) } @@ -205,6 +206,6 @@ pub(super) fn parse_toml_global_state>( return Ok(None); } let bytes = file_utils::read_file(update_path)?; - let config: GlobalStateUpdateConfig = toml::from_slice(&bytes)?; + let config = toml::from_str(std::str::from_utf8(&bytes).unwrap())?; Ok(Some((config, Bytes::from(bytes)))) } diff --git a/node/src/utils/specimen.rs b/node/src/utils/specimen.rs index 14f2ea9f5a..cd7c43d67f 100644 --- a/node/src/utils/specimen.rs +++ b/node/src/utils/specimen.rs @@ -27,8 +27,8 @@ use casper_types::{ ExecutableDeployItem, FinalitySignature, FinalitySignatureId, FinalitySignatureV2, PackageHash, ProtocolVersion, RewardedSignatures, RuntimeArgs, SecretKey, SemVer, SignedBlockHeader, SingleBlockRewardedSignatures, TimeDiff, Timestamp, Transaction, TransactionCategory, - TransactionHash, TransactionId, TransactionV1, TransactionV1Builder, TransactionV1Hash, URef, - KEY_HASH_LENGTH, U512, + TransactionHash, TransactionId, TransactionSessionKind, TransactionV1, TransactionV1Builder, + TransactionV1Hash, URef, KEY_HASH_LENGTH, U512, }; use crate::{ @@ -988,14 +988,19 @@ impl LargestSpecimen for TransactionV1Hash { impl LargestSpecimen for TransactionV1 { fn largest_specimen(estimator: &E, cache: &mut Cache) -> Self { - TransactionV1Builder::new_transfer( - LargestSpecimen::largest_specimen(estimator, cache), - LargestSpecimen::largest_specimen(estimator, cache), - U512::largest_specimen(estimator, cache), - LargestSpecimen::largest_specimen(estimator, cache), - LargestSpecimen::largest_specimen(estimator, cache), + // See comment in `impl LargestSpecimen for ExecutableDeployItem` below for rationale here. + let max_size_with_margin = + estimator.parameter::("max_transaction_size").max(0) as usize + 10 * 4; + + TransactionV1Builder::new_session( + TransactionSessionKind::Installer, + Bytes::from(vec_of_largest_specimen( + estimator, + max_size_with_margin, + cache, + )), + "a", ) - .unwrap() .with_secret_key(&LargestSpecimen::largest_specimen(estimator, cache)) .with_timestamp(LargestSpecimen::largest_specimen(estimator, cache)) .with_ttl(LargestSpecimen::largest_specimen(estimator, cache)) diff --git a/resources/local/chainspec.toml.in b/resources/local/chainspec.toml.in index 3de356c90e..8a10d5f73e 100644 --- a/resources/local/chainspec.toml.in +++ b/resources/local/chainspec.toml.in @@ -89,18 +89,37 @@ allow_unrestricted_transfers = true compute_rewards = true # Defines how refunds of the unused portion of payment amounts are calculated and handled. # -# The only valid value for 'type' is currently 'refund'. This causes excess payment amounts to be sent to either a +# Valid options are: +# 'refund': a ratio of the unspent token is returned to the spender. +# 'burn': a ratio of the unspent token is burned. +# 'no_refund': no refunds are paid out; this is functionally equivalent to refund with 0% ratio. +# This causes excess payment amounts to be sent to either a # pre-defined purse, or back to the sender. The refunded amount is calculated as the given ratio of the payment amount # minus the execution costs. -refund_handling = { type = 'refund', refund_ratio = [99, 100] } +refund_handling = { type = 'no_refund' } # Defines how fees are handled. # # Valid options are: +# 'no_fee': fees are eliminated. # 'pay_to_proposer': fees are paid to the block proposer # 'accumulate': fees are accumulated in a special purse and distributed at the end of each era evenly among all # administrator accounts # 'burn': fees are burned -fee_handling = { type = 'pay_to_proposer' } +fee_handling = { type = 'no_fee' } +# Defines how fees are handled. +# +# Valid options are: +# 'classic': senders of transaction self-specify how much they pay. +# 'fixed': costs are fixed, per the cost table +# 'reserved': prepaid transaction (currently not supported) +pricing_handling = { type = 'fixed' } +# Does the network allow pre-payment / reservations for future +# execution? Currently not supported. +# +allow_reservations = false +# +# How long does it take for a balance hold to fade away? +balance_hold_interval = '24 hours' # List of public keys of administrator accounts. Setting this option makes only on private chains which require # administrator accounts for regulatory reasons. administrators = [] @@ -117,22 +136,20 @@ reduced_reward_multiplier = [1, 5] max_ttl = '18 hours' # Maximum transaction size in bytes. Size is of the transaction when serialized via ToBytes. max_transaction_size = 1_048_576 -# Maximum number of transfer transactions allowed in a block. -block_max_mint_count = 1000 -# Maximum number of staking transactions allowed in a block. -block_max_auction_count = 200 +# Maximum number of mint transactions (i.e. transfers) allowed in a block. +block_max_mint_count = 500 +# Maximum number of auction transactions allowed in a block. +block_max_auction_count = 100 # Maximum number of installer/upgrader transactions allowed in a block. block_max_install_upgrade_count = 2 # Maximum number of other transactions (non-transfer, non-staking, non-installer/upgrader) allowed in a block. -block_max_standard_count = 100 +block_max_standard_count = 50 # The maximum number of approvals permitted in a single block. block_max_approval_count = 2600 # Maximum block size in bytes including transactions contained by the block. 0 means unlimited. max_block_size = 10_485_760 # The upper limit of total gas of all transactions in a block. block_gas_limit = 10_000_000_000_000 -# Chainspec configured cost for native transfers. -native_transfer_cost = 2_500_000_000 # The minimum amount in motes for a valid native transfer. native_transfer_minimum_motes = 2_500_000_000 # The maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the config.toml file. @@ -271,8 +288,8 @@ max_topics_per_contract = 128 max_message_size = 1_024 [system_costs] -install_upgrade_gas_limit = 0 -standard_transaction_gas_limit = 0 +install_upgrade_gas_limit = 3_500_000_000_000 +standard_transaction_gas_limit = 500_000_000_000 [system_costs.auction_costs] get_era_validators = 10_000 diff --git a/resources/production/chainspec.toml b/resources/production/chainspec.toml index d7dfe953ca..70d713659f 100644 --- a/resources/production/chainspec.toml +++ b/resources/production/chainspec.toml @@ -100,18 +100,35 @@ compute_rewards = true # Defines how refunds of the unused portion of payment amounts are calculated and handled. # # Valid options are: -# 'refund': this causes excess payment amounts to be sent to either a pre-defined purse, or back to the sender. -# the refunded amount is calculated as the given ratio of the payment amount minus the execution costs. -# 'burn': similar to what refund does; except the refund amount is burned. +# 'refund': a ratio of the unspent token is returned to the spender. +# 'burn': a ratio of the unspent token is burned. +# 'no_refund': no refunds are paid out; this is functionally equivalent to refund with 0% ratio. +# This causes excess payment amounts to be sent to either a +# pre-defined purse, or back to the sender. The refunded amount is calculated as the given ratio of the payment amount +# minus the execution costs. refund_handling = { type = 'refund', refund_ratio = [99, 100] } # Defines how fees are handled. # # Valid options are: +# 'no_fee': fees are eliminated. # 'pay_to_proposer': fees are paid to the block proposer # 'accumulate': fees are accumulated in a special purse and distributed at the end of each era evenly among all # administrator accounts # 'burn': fees are burned -fee_handling = { type = 'pay_to_proposer' } +fee_handling = { type = 'no_fee' } +# Defines how fees are handled. +# +# Valid options are: +# 'classic': senders of transaction self-specify how much they pay. +# 'fixed': costs are fixed, per the cost table +# 'reserved': prepaid transaction (currently not supported) +pricing_handling = { type = 'fixed' } +# Does the network allow pre-payment / reservations for future +# execution? Currently not supported. +# +allow_reservations = false +# How long does it take for a balance hold to fade away? +balance_hold_interval = '24 hours' # List of public keys of administrator accounts. Setting this option makes only on private chains which require # administrator accounts for regulatory reasons. administrators = [] @@ -128,22 +145,20 @@ reduced_reward_multiplier = [1, 5] max_ttl = '18 hours' # Maximum transaction size in bytes. Size is of the transaction when serialized via ToBytes. max_transaction_size = 1_048_576 -# Maximum number of transfer transactions allowed in a block. -block_max_mint_count = 1000 -# Maximum number of staking transactions allowed in a block. -block_max_auction_count = 200 +# Maximum number of mint transactions (i.e. transfers) allowed in a block. +block_max_mint_count = 500 +# Maximum number of auction (staking) transactions allowed in a block. +block_max_auction_count = 100 # Maximum number of installer/upgrader transactions allowed in a block. block_max_install_upgrade_count = 2 # Maximum number of other transactions (non-transfer, non-staking, non-installer/upgrader) allowed in a block. -block_max_standard_count = 100 +block_max_standard_count = 50 # The maximum number of approvals permitted in a single block. block_max_approval_count = 2600 # Maximum block size in bytes including transactions contained by the block. 0 means unlimited. max_block_size = 10_485_760 # The upper limit of total gas of all transactions in a block. block_gas_limit = 4_000_000_000_000 -# Chainspec configured cost for native transfers. -native_transfer_cost = 2_500_000_000 # The minimum amount in motes for a valid native transfer. native_transfer_minimum_motes = 2_500_000_000 # The maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the config.toml file. @@ -282,8 +297,8 @@ max_topics_per_contract = 128 max_message_size = 1_024 [system_costs] -install_upgrade_gas_limit = 0 -standard_transaction_gas_limit = 0 +install_upgrade_gas_limit = 3_500_000_000_000 +standard_transaction_gas_limit = 500_000_000_000 [system_costs.auction_costs] get_era_validators = 10_000 diff --git a/resources/test/sse_data_schema.json b/resources/test/sse_data_schema.json index 09eeee2a0f..9c1147ab4c 100644 --- a/resources/test/sse_data_schema.json +++ b/resources/test/sse_data_schema.json @@ -1637,8 +1637,9 @@ "Classic": { "type": "object", "required": [ - "gas_price", - "payment_amount" + "gas_price_tolerance", + "payment_amount", + "standard_payment" ], "properties": { "payment_amount": { @@ -1647,11 +1648,15 @@ "format": "uint64", "minimum": 0.0 }, - "gas_price": { - "description": "User-specified gas_price tolerance (minimum 1).", + "gas_price_tolerance": { + "description": "User-specified gas_price tolerance (minimum 1). This is interpreted to mean \"do not include this transaction in a block if the current gas price is greater than this number\"", "type": "integer", - "format": "uint64", + "format": "uint8", "minimum": 0.0 + }, + "standard_payment": { + "description": "Standard payment.", + "type": "boolean" } }, "additionalProperties": false @@ -1675,7 +1680,7 @@ "gas_price_tolerance": { "description": "User-specified gas_price tolerance (minimum 1). This is interpreted to mean \"do not include this transaction in a block if the current gas price is greater than this number\"", "type": "integer", - "format": "uint64", + "format": "uint8", "minimum": 0.0 } }, @@ -1695,7 +1700,8 @@ "type": "object", "required": [ "paid_amount", - "receipt" + "receipt", + "strike_price" ], "properties": { "receipt": { @@ -1708,11 +1714,15 @@ }, "paid_amount": { "description": "Price paid in the past to reserve space in a future block.", - "allOf": [ - { - "$ref": "#/definitions/U512" - } - ] + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "strike_price": { + "description": "The gas price at the time of reservation.", + "type": "integer", + "format": "uint8", + "minimum": 0.0 } }, "additionalProperties": false @@ -1882,10 +1892,10 @@ "description": "Hex-encoded entity address identifying the invocable entity.", "type": "object", "required": [ - "InvocableEntity" + "ByHash" ], "properties": { - "InvocableEntity": { + "ByHash": { "type": "string" } }, @@ -1895,10 +1905,10 @@ "description": "The alias identifying the invocable entity.", "type": "object", "required": [ - "InvocableEntityAlias" + "ByName" ], "properties": { - "InvocableEntityAlias": { + "ByName": { "type": "string" } }, @@ -1908,10 +1918,10 @@ "description": "The address and optional version identifying the package.", "type": "object", "required": [ - "Package" + "ByPackageHash" ], "properties": { - "Package": { + "ByPackageHash": { "type": "object", "required": [ "addr" @@ -1940,16 +1950,16 @@ "description": "The alias and optional version identifying the package.", "type": "object", "required": [ - "PackageAlias" + "ByPackageName" ], "properties": { - "PackageAlias": { + "ByPackageName": { "type": "object", "required": [ - "alias" + "name" ], "properties": { - "alias": { + "name": { "description": "The package alias.", "type": "string" }, @@ -2179,7 +2189,7 @@ ] }, "transfers": { - "description": "A record of Transfers performed while executing the deploy.", + "description": "A record of version 1 Transfers performed while executing the deploy.", "type": "array", "items": { "$ref": "#/definitions/TransferAddr" @@ -2444,14 +2454,14 @@ "additionalProperties": false }, { - "description": "Writes the given Transfer to global state.", + "description": "Writes the given version 1 Transfer to global state.", "type": "object", "required": [ "WriteTransfer" ], "properties": { "WriteTransfer": { - "$ref": "#/definitions/Transfer" + "$ref": "#/definitions/TransferV1" } }, "additionalProperties": false @@ -2653,7 +2663,7 @@ ] }, "transfers": { - "description": "Transfers performed by the Deploy.", + "description": "Version 1 transfers performed by the Deploy.", "type": "array", "items": { "$ref": "#/definitions/TransferAddr" @@ -2687,7 +2697,7 @@ "additionalProperties": false }, "TransferAddr": { - "description": "Hex-encoded transfer address.", + "description": "Hex-encoded version 1 transfer address.", "type": "string" }, "URef": { @@ -2796,8 +2806,8 @@ } ] }, - "Transfer": { - "description": "Represents a transfer from one purse to another", + "TransferV1": { + "description": "Represents a version 1 transfer from one purse to another.", "type": "object", "required": [ "amount", @@ -3297,103 +3307,221 @@ "additionalProperties": false }, "ExecutionResultV2": { - "description": "The result of executing a single deploy.", + "description": "The result of executing a single transaction.", + "type": "object", + "required": [ + "consumed", + "cost", + "effects", + "initiator", + "limit", + "payment", + "transfers" + ], + "properties": { + "initiator": { + "description": "Who initiatied this transaction.", + "allOf": [ + { + "$ref": "#/definitions/InitiatorAddr" + } + ] + }, + "error_message": { + "description": "If there is no error message, this execution was processed successfully. If there is an error message, this execution failed to fully process for the stated reason.", + "type": [ + "string", + "null" + ] + }, + "limit": { + "description": "What was the maximum allowed gas limit for this transaction?.", + "allOf": [ + { + "$ref": "#/definitions/Gas" + } + ] + }, + "consumed": { + "description": "How much gas was consumed executing this transaction.", + "allOf": [ + { + "$ref": "#/definitions/Gas" + } + ] + }, + "cost": { + "description": "How much was paid for this transaction.", + "allOf": [ + { + "$ref": "#/definitions/U512" + } + ] + }, + "payment": { + "description": "Breakdown of payments made to cover the cost.", + "type": "array", + "items": { + "$ref": "#/definitions/PaymentInfo" + } + }, + "transfers": { + "description": "A record of transfers performed while executing this transaction.", + "type": "array", + "items": { + "$ref": "#/definitions/Transfer" + } + }, + "effects": { + "description": "The effects of executing this transaction.", + "allOf": [ + { + "$ref": "#/definitions/Effects" + } + ] + } + }, + "additionalProperties": false + }, + "Gas": { + "description": "The `Gas` struct represents a `U512` amount of gas.", + "allOf": [ + { + "$ref": "#/definitions/U512" + } + ] + }, + "PaymentInfo": { + "description": "Breakdown of payments made to cover the cost.", + "type": "object", + "required": [ + "source" + ], + "properties": { + "source": { + "description": "Source purse used for payment of the transaction.", + "allOf": [ + { + "$ref": "#/definitions/URef" + } + ] + } + } + }, + "Transfer": { + "description": "A versioned wrapper for a transfer.", "oneOf": [ { - "description": "The result of a failed execution.", + "description": "A version 1 transfer.", "type": "object", "required": [ - "Failure" + "Version1" ], "properties": { - "Failure": { - "type": "object", - "required": [ - "cost", - "effects", - "error_message", - "transfers" - ], - "properties": { - "effects": { - "description": "The effects of executing the deploy.", - "allOf": [ - { - "$ref": "#/definitions/Effects" - } - ] - }, - "transfers": { - "description": "A record of transfers performed while executing the deploy.", - "type": "array", - "items": { - "$ref": "#/definitions/TransferAddr" - } - }, - "cost": { - "description": "The cost in Motes of executing the deploy.", - "allOf": [ - { - "$ref": "#/definitions/U512" - } - ] - }, - "error_message": { - "description": "The error message associated with executing the deploy.", - "type": "string" - } - }, - "additionalProperties": false + "Version1": { + "$ref": "#/definitions/TransferV1" } }, "additionalProperties": false }, { - "description": "The result of a successful execution.", + "description": "A version 2 transfer.", "type": "object", "required": [ - "Success" + "Version2" ], "properties": { - "Success": { - "type": "object", - "required": [ - "cost", - "effects", - "transfers" - ], - "properties": { - "effects": { - "description": "The effects of executing the deploy.", - "allOf": [ - { - "$ref": "#/definitions/Effects" - } - ] - }, - "transfers": { - "description": "A record of transfers performed while executing the deploy.", - "type": "array", - "items": { - "$ref": "#/definitions/TransferAddr" - } - }, - "cost": { - "description": "The cost in Motes of executing the deploy.", - "allOf": [ - { - "$ref": "#/definitions/U512" - } - ] - } - }, - "additionalProperties": false + "Version2": { + "$ref": "#/definitions/TransferV2" } }, "additionalProperties": false } ] }, + "TransferV2": { + "description": "Represents a version 2 transfer from one purse to another.", + "type": "object", + "required": [ + "amount", + "from", + "gas", + "source", + "target", + "transaction_hash" + ], + "properties": { + "transaction_hash": { + "description": "Transaction that created the transfer.", + "allOf": [ + { + "$ref": "#/definitions/TransactionHash" + } + ] + }, + "from": { + "description": "Entity from which transfer was executed.", + "allOf": [ + { + "$ref": "#/definitions/InitiatorAddr" + } + ] + }, + "to": { + "description": "Account to which funds are transferred.", + "anyOf": [ + { + "$ref": "#/definitions/AccountHash" + }, + { + "type": "null" + } + ] + }, + "source": { + "description": "Source purse.", + "allOf": [ + { + "$ref": "#/definitions/URef" + } + ] + }, + "target": { + "description": "Target purse.", + "allOf": [ + { + "$ref": "#/definitions/URef" + } + ] + }, + "amount": { + "description": "Transfer amount.", + "allOf": [ + { + "$ref": "#/definitions/U512" + } + ] + }, + "gas": { + "description": "Gas.", + "allOf": [ + { + "$ref": "#/definitions/Gas" + } + ] + }, + "id": { + "description": "User-defined ID.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, "Effects": { "description": "A log of all transforms produced during execution.", "type": "array", @@ -3419,7 +3547,7 @@ "additionalProperties": false }, "TransformKindV2": { - "description": "Representation of a single transformation occurring during execution.\n\nNote that all arithmetic variants of [`TransformKind`] are commutative which means that a given collection of them can be executed in any order to produce the same end result.", + "description": "Representation of a single transformation occurring during execution.\n\nNote that all arithmetic variants of `TransformKindV2` are commutative which means that a given collection of them can be executed in any order to produce the same end result.", "oneOf": [ { "description": "An identity transformation that does not modify a value in the global state.\n\nCreated as a result of reading from the global state.", @@ -3619,14 +3747,14 @@ "additionalProperties": false }, { - "description": "A `Transfer`.", + "description": "A version 1 (legacy) transfer.", "type": "object", "required": [ - "Transfer" + "LegacyTransfer" ], "properties": { - "Transfer": { - "$ref": "#/definitions/Transfer" + "LegacyTransfer": { + "$ref": "#/definitions/TransferV1" } }, "additionalProperties": false @@ -4066,21 +4194,21 @@ "description": "Context of method execution\n\nMost significant bit represents version i.e. - 0b0 -> 0.x/1.x (session & contracts) - 0b1 -> 2.x and later (introduced installer, utility entry points)", "oneOf": [ { - "description": "Runs as session code (caller) Deprecated, retained to allow read back of legacy stored session.", + "description": "Runs using the calling entity's context. In v1.x this was used for both \"session\" code run using the originating Account's context, and also for \"StoredSession\" code that ran in the caller's context. While this made systemic sense due to the way the runtime context nesting works, this dual usage was very confusing to most human beings.\n\nIn v2.x the renamed Caller variant is exclusively used for wasm run using the initiating account entity's context. Previously installed 1.x stored session code should continue to work as the binary value matches but we no longer allow such logic to be upgraded, nor do we allow new stored session to be installed.", "type": "string", "enum": [ - "Session" + "Caller" ] }, { - "description": "Runs within called entity's context (called)", + "description": "Runs using the called entity's context.", "type": "string", "enum": [ - "AddressableEntity" + "Called" ] }, { - "description": "This entry point is intended to extract a subset of bytecode. Runs within called entity's context (called)", + "description": "Extract a subset of bytecode and installs it as a new smart contract. Runs using the called entity's context.", "type": "string", "enum": [ "Factory" @@ -4733,14 +4861,14 @@ "type": "object", "required": [ "block_index", - "entity_addr", + "entity_hash", "message", "topic_index", "topic_name", "topic_name_hash" ], "properties": { - "entity_addr": { + "entity_hash": { "description": "The identity of the entity that produced the message.", "allOf": [ { diff --git a/smart_contracts/contract/src/contract_api/runtime.rs b/smart_contracts/contract/src/contract_api/runtime.rs index abd69f436e..1eadc136c0 100644 --- a/smart_contracts/contract/src/contract_api/runtime.rs +++ b/smart_contracts/contract/src/contract_api/runtime.rs @@ -9,10 +9,10 @@ use casper_types::{ api_error, bytesrepr::{self, FromBytes}, contract_messages::{MessagePayload, MessageTopicOperation}, - package::EntityVersion, system::Caller, - AddressableEntityHash, ApiError, BlockTime, CLTyped, CLValue, Key, PackageHash, Phase, - RuntimeArgs, URef, BLAKE2B_DIGEST_LENGTH, BLOCKTIME_SERIALIZED_LENGTH, PHASE_SERIALIZED_LENGTH, + AddressableEntityHash, ApiError, BlockTime, CLTyped, CLValue, EntityVersion, Key, PackageHash, + Phase, RuntimeArgs, URef, BLAKE2B_DIGEST_LENGTH, BLOCKTIME_SERIALIZED_LENGTH, + PHASE_SERIALIZED_LENGTH, }; use crate::{contract_api, ext_ffi, unwrap_or_revert::UnwrapOrRevert}; diff --git a/smart_contracts/contract/src/contract_api/storage.rs b/smart_contracts/contract/src/contract_api/storage.rs index 5e1825f17e..c0ebdcd74e 100644 --- a/smart_contracts/contract/src/contract_api/storage.rs +++ b/smart_contracts/contract/src/contract_api/storage.rs @@ -13,9 +13,8 @@ use casper_types::{ api_error, bytesrepr::{self, FromBytes, ToBytes}, contract_messages::MessageTopicOperation, - package::EntityVersion, - AccessRights, AddressableEntityHash, ApiError, CLTyped, CLValue, HashAddr, Key, PackageHash, - URef, DICTIONARY_ITEM_KEY_MAX_LENGTH, UREF_SERIALIZED_LENGTH, + AccessRights, AddressableEntityHash, ApiError, CLTyped, CLValue, EntityVersion, HashAddr, Key, + PackageHash, URef, DICTIONARY_ITEM_KEY_MAX_LENGTH, UREF_SERIALIZED_LENGTH, }; use crate::{ diff --git a/smart_contracts/contract/src/ext_ffi.rs b/smart_contracts/contract/src/ext_ffi.rs index 1f1e4245be..10a574a711 100644 --- a/smart_contracts/contract/src/ext_ffi.rs +++ b/smart_contracts/contract/src/ext_ffi.rs @@ -2,6 +2,10 @@ //! //! Generally should not be used directly. See the [`contract_api`](crate::contract_api) for //! high-level bindings suitable for writing smart contracts. + +#[cfg(doc)] +use alloc::collections::BTreeMap; + extern "C" { /// The bytes in the span of wasm memory from `key_ptr` to `key_ptr + key_size` must correspond /// to a valid global state key, otherwise the function will fail. If the key is de-serialized diff --git a/smart_contracts/contracts/client/activate-bid/src/main.rs b/smart_contracts/contracts/client/activate-bid/src/main.rs index 327406e028..2e040b2aa6 100644 --- a/smart_contracts/contracts/client/activate-bid/src/main.rs +++ b/smart_contracts/contracts/client/activate-bid/src/main.rs @@ -4,12 +4,12 @@ use casper_contract::contract_api::{runtime, system}; use casper_types::{runtime_args, system::auction, PublicKey}; -const ARG_VALIDATOR_PUBLIC_KEY: &str = "validator_public_key"; +const ARG_VALIDATOR: &str = "validator"; fn activate_bid(public_key: PublicKey) { let contract_hash = system::get_auction(); let args = runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => public_key, + auction::ARG_VALIDATOR => public_key, }; runtime::call_contract::<()>(contract_hash, auction::METHOD_ACTIVATE_BID, args); } @@ -17,6 +17,6 @@ fn activate_bid(public_key: PublicKey) { // Accepts a public key. Issues an activate-bid bid to the auction contract. #[no_mangle] pub extern "C" fn call() { - let public_key: PublicKey = runtime::get_named_arg(ARG_VALIDATOR_PUBLIC_KEY); + let public_key: PublicKey = runtime::get_named_arg(ARG_VALIDATOR); activate_bid(public_key); } diff --git a/smart_contracts/contracts/explorer/faucet-stored/src/main.rs b/smart_contracts/contracts/explorer/faucet-stored/src/main.rs index 835a6cb6ff..ba33a0c867 100644 --- a/smart_contracts/contracts/explorer/faucet-stored/src/main.rs +++ b/smart_contracts/contracts/explorer/faucet-stored/src/main.rs @@ -114,7 +114,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let set_variables = EntryPoint::new( @@ -135,7 +135,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let authorize_to = EntryPoint::new( @@ -146,7 +146,7 @@ pub extern "C" fn call() { )], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(faucet); diff --git a/smart_contracts/contracts/profiling/host-function-metrics/src/lib.rs b/smart_contracts/contracts/profiling/host-function-metrics/src/lib.rs index 0d7bce2a18..edafa474b0 100644 --- a/smart_contracts/contracts/profiling/host-function-metrics/src/lib.rs +++ b/smart_contracts/contracts/profiling/host-function-metrics/src/lib.rs @@ -228,7 +228,7 @@ fn store_function( ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/add-gas-subcall/src/main.rs b/smart_contracts/contracts/test/add-gas-subcall/src/main.rs index b66757318a..070cfa079f 100644 --- a/smart_contracts/contracts/test/add-gas-subcall/src/main.rs +++ b/smart_contracts/contracts/test/add-gas-subcall/src/main.rs @@ -55,7 +55,7 @@ fn store() -> (AddressableEntityHash, EntityVersion) { vec![Parameter::new(ARG_GAS_AMOUNT, CLType::I32)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/contract-context/src/main.rs b/smart_contracts/contracts/test/contract-context/src/main.rs index 63f82547a9..4aeb4bc26a 100644 --- a/smart_contracts/contracts/test/contract-context/src/main.rs +++ b/smart_contracts/contracts/test/contract-context/src/main.rs @@ -11,8 +11,8 @@ use casper_contract::{ }; use casper_types::{ addressable_entity::{EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, NamedKeys}, - package::ENTITY_INITIAL_VERSION, runtime_args, AddressableEntityHash, CLType, EntityVersion, Key, PackageHash, + ENTITY_INITIAL_VERSION, }; const PACKAGE_HASH_KEY: &str = "package_hash_key"; @@ -97,7 +97,7 @@ fn create_entrypoints_1() -> EntryPoints { Vec::new(), CLType::I32, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(contract_code_test); @@ -106,7 +106,7 @@ fn create_entrypoints_1() -> EntryPoints { Vec::new(), CLType::I32, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(session_code_caller_as_contract); diff --git a/smart_contracts/contracts/test/contract-funds/src/main.rs b/smart_contracts/contracts/test/contract-funds/src/main.rs index ae59493d5a..70c28afe37 100644 --- a/smart_contracts/contracts/test/contract-funds/src/main.rs +++ b/smart_contracts/contracts/test/contract-funds/src/main.rs @@ -45,7 +45,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_TARGET, AccountHash::cl_type())], URef::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(faucet_entrypoint); diff --git a/smart_contracts/contracts/test/contract-messages-emitter/src/main.rs b/smart_contracts/contracts/test/contract-messages-emitter/src/main.rs index b1191decd7..9d010d1a79 100644 --- a/smart_contracts/contracts/test/contract-messages-emitter/src/main.rs +++ b/smart_contracts/contracts/test/contract-messages-emitter/src/main.rs @@ -91,28 +91,28 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); emitter_entry_points.add_entry_point(EntryPoint::new( ENTRY_POINT_EMIT_MESSAGE, vec![Parameter::new(ARG_MESSAGE_SUFFIX_NAME, String::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); emitter_entry_points.add_entry_point(EntryPoint::new( ENTRY_POINT_ADD_TOPIC, vec![Parameter::new(ARG_TOPIC_NAME, String::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); emitter_entry_points.add_entry_point(EntryPoint::new( ENTRY_POINT_EMIT_MULTIPLE_MESSAGES, vec![Parameter::new(ARG_NUM_MESSAGES_TO_EMIT, u32::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); if register_topic_with_init { diff --git a/smart_contracts/contracts/test/contract-messages-upgrader/src/main.rs b/smart_contracts/contracts/test/contract-messages-upgrader/src/main.rs index 273e893660..4b884466fb 100644 --- a/smart_contracts/contracts/test/contract-messages-upgrader/src/main.rs +++ b/smart_contracts/contracts/test/contract-messages-upgrader/src/main.rs @@ -105,21 +105,21 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); emitter_entry_points.add_entry_point(EntryPoint::new( ENTRY_POINT_EMIT_MESSAGE, vec![Parameter::new(ARG_MESSAGE_SUFFIX_NAME, String::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); emitter_entry_points.add_entry_point(EntryPoint::new( ENTRY_POINT_EMIT_MESSAGE_FROM_EACH_VERSION, vec![Parameter::new(ARG_MESSAGE_SUFFIX_NAME, String::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let message_emitter_package_hash: PackageHash = runtime::get_key(PACKAGE_HASH_KEY_NAME) diff --git a/smart_contracts/contracts/test/counter-factory/src/main.rs b/smart_contracts/contracts/test/counter-factory/src/main.rs index 665b6e1987..fab271c793 100644 --- a/smart_contracts/contracts/test/counter-factory/src/main.rs +++ b/smart_contracts/contracts/test/counter-factory/src/main.rs @@ -85,7 +85,7 @@ fn installer(name: String, initial_value: U512) { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point: EntryPoint = EntryPoint::new( @@ -93,7 +93,7 @@ fn installer(name: String, initial_value: U512) { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -138,7 +138,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Template, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point: EntryPoint = EntryPoint::new( @@ -146,7 +146,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Template, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/deserialize-error/src/main.rs b/smart_contracts/contracts/test/deserialize-error/src/main.rs index c0b16dd85b..5836be1174 100644 --- a/smart_contracts/contracts/test/deserialize-error/src/main.rs +++ b/smart_contracts/contracts/test/deserialize-error/src/main.rs @@ -81,7 +81,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/dictionary/src/lib.rs b/smart_contracts/contracts/test/dictionary/src/lib.rs index be79645de7..79e0cfa84d 100644 --- a/smart_contracts/contracts/test/dictionary/src/lib.rs +++ b/smart_contracts/contracts/test/dictionary/src/lib.rs @@ -183,35 +183,35 @@ pub fn delegate() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( SHARE_RO_ENTRYPOINT, Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( SHARE_W_ENTRYPOINT, Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( INVALID_PUT_DICTIONARY_ITEM_KEY_ENTRYPOINT, Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( INVALID_GET_DICTIONARY_ITEM_KEY_ENTRYPOINT, Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let named_keys = { let uref = { diff --git a/smart_contracts/contracts/test/do-nothing-stored-caller/src/main.rs b/smart_contracts/contracts/test/do-nothing-stored-caller/src/main.rs index 98a775116e..aa8fd582c1 100644 --- a/smart_contracts/contracts/test/do-nothing-stored-caller/src/main.rs +++ b/smart_contracts/contracts/test/do-nothing-stored-caller/src/main.rs @@ -6,7 +6,7 @@ extern crate alloc; use alloc::string::String; use casper_contract::contract_api::runtime; -use casper_types::{package::EntityVersion, runtime_args, PackageHash}; +use casper_types::{runtime_args, EntityVersion, PackageHash}; const ENTRY_FUNCTION_NAME: &str = "delegate"; const PURSE_NAME_ARG_NAME: &str = "purse_name"; diff --git a/smart_contracts/contracts/test/do-nothing-stored-upgrader/src/main.rs b/smart_contracts/contracts/test/do-nothing-stored-upgrader/src/main.rs index 97d04fa005..e5d18a1a34 100644 --- a/smart_contracts/contracts/test/do-nothing-stored-upgrader/src/main.rs +++ b/smart_contracts/contracts/test/do-nothing-stored-upgrader/src/main.rs @@ -42,7 +42,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE_NAME, String::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(delegate); diff --git a/smart_contracts/contracts/test/do-nothing-stored/src/main.rs b/smart_contracts/contracts/test/do-nothing-stored/src/main.rs index 33e65f19d0..401982ae38 100644 --- a/smart_contracts/contracts/test/do-nothing-stored/src/main.rs +++ b/smart_contracts/contracts/test/do-nothing-stored/src/main.rs @@ -27,7 +27,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); entry_points diff --git a/smart_contracts/contracts/test/ee-1071-regression/src/main.rs b/smart_contracts/contracts/test/ee-1071-regression/src/main.rs index c37dbe1838..90ff40021a 100644 --- a/smart_contracts/contracts/test/ee-1071-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-1071-regression/src/main.rs @@ -26,7 +26,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/ee-1129-regression/src/main.rs b/smart_contracts/contracts/test/ee-1129-regression/src/main.rs index 57bade8faf..a8340814a1 100644 --- a/smart_contracts/contracts/test/ee-1129-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-1129-regression/src/main.rs @@ -33,7 +33,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/ee-1217-regression/src/main.rs b/smart_contracts/contracts/test/ee-1217-regression/src/main.rs index e73848d1e4..c23cb4a107 100644 --- a/smart_contracts/contracts/test/ee-1217-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-1217-regression/src/main.rs @@ -68,10 +68,10 @@ pub extern "C" fn withdraw_bid_session() { } fn activate_bid() { - let public_key: PublicKey = runtime::get_named_arg(auction::ARG_VALIDATOR_PUBLIC_KEY); + let public_key: PublicKey = runtime::get_named_arg(auction::ARG_VALIDATOR); let auction = system::get_auction(); let args = runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => public_key, + auction::ARG_VALIDATOR => public_key, }; runtime::call_contract::<()>(auction, auction::METHOD_ACTIVATE_BID, args); } @@ -141,70 +141,70 @@ pub extern "C" fn call() { vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let add_bid_contract_entry_point = EntryPoint::new( METHOD_ADD_BID_CONTRACT_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let withdraw_bid_session_entry_point = EntryPoint::new( METHOD_WITHDRAW_BID_SESSION_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let withdraw_bid_contract_entry_point = EntryPoint::new( METHOD_WITHDRAW_BID_CONTRACT_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let delegate_session_entry_point = EntryPoint::new( METHOD_DELEGATE_SESSION_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let delegate_contract_entry_point = EntryPoint::new( METHOD_DELEGATE_CONTRACT_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let undelegate_session_entry_point = EntryPoint::new( METHOD_UNDELEGATE_SESSION_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let undelegate_contract_entry_point = EntryPoint::new( METHOD_UNDELEGATE_CONTRACT_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let activate_bid_session_entry_point = EntryPoint::new( METHOD_ACTIVATE_BID_SESSION_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let activate_bid_contract_entry_point = EntryPoint::new( METHOD_ACTIVATE_BID_CONTRACT_NAME.to_string(), vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(add_bid_session_entry_point); entry_points.add_entry_point(add_bid_contract_entry_point); diff --git a/smart_contracts/contracts/test/ee-401-regression/src/main.rs b/smart_contracts/contracts/test/ee-401-regression/src/main.rs index 4183f37072..b1b6bcff70 100644 --- a/smart_contracts/contracts/test/ee-401-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-401-regression/src/main.rs @@ -35,7 +35,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/ee-441-rng-state/src/main.rs b/smart_contracts/contracts/test/ee-441-rng-state/src/main.rs index 864ed084e3..e328ce8505 100644 --- a/smart_contracts/contracts/test/ee-441-rng-state/src/main.rs +++ b/smart_contracts/contracts/test/ee-441-rng-state/src/main.rs @@ -44,7 +44,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::String, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(do_nothing_entry_point); @@ -54,7 +54,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(do_something_entry_point); diff --git a/smart_contracts/contracts/test/ee-572-regression-create/src/main.rs b/smart_contracts/contracts/test/ee-572-regression-create/src/main.rs index b4c6726fda..92ee1dbc00 100644 --- a/smart_contracts/contracts/test/ee-572-regression-create/src/main.rs +++ b/smart_contracts/contracts/test/ee-572-regression-create/src/main.rs @@ -34,7 +34,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/ee-599-regression/src/main.rs b/smart_contracts/contracts/test/ee-599-regression/src/main.rs index d232b6b120..31e4a54773 100644 --- a/smart_contracts/contracts/test/ee-599-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-599-regression/src/main.rs @@ -132,7 +132,7 @@ fn delegate() -> Result<(), ApiError> { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_1); @@ -142,7 +142,7 @@ fn delegate() -> Result<(), ApiError> { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_2); @@ -152,7 +152,7 @@ fn delegate() -> Result<(), ApiError> { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_3); @@ -162,7 +162,7 @@ fn delegate() -> Result<(), ApiError> { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_4); diff --git a/smart_contracts/contracts/test/ee-771-regression/src/main.rs b/smart_contracts/contracts/test/ee-771-regression/src/main.rs index 12414d68a5..21328e8658 100644 --- a/smart_contracts/contracts/test/ee-771-regression/src/main.rs +++ b/smart_contracts/contracts/test/ee-771-regression/src/main.rs @@ -39,7 +39,7 @@ pub extern "C" fn contract_ext() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -61,7 +61,7 @@ fn store(named_keys: NamedKeys) -> (AddressableEntityHash, EntityVersion) { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/expensive-calculation/src/main.rs b/smart_contracts/contracts/test/expensive-calculation/src/main.rs index ed69b3da6e..3f8607975c 100644 --- a/smart_contracts/contracts/test/expensive-calculation/src/main.rs +++ b/smart_contracts/contracts/test/expensive-calculation/src/main.rs @@ -34,7 +34,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); entry_points diff --git a/smart_contracts/contracts/test/get-call-stack-recursive-subcall/src/main.rs b/smart_contracts/contracts/test/get-call-stack-recursive-subcall/src/main.rs index 6dac6d58d1..a7ec5dd402 100644 --- a/smart_contracts/contracts/test/get-call-stack-recursive-subcall/src/main.rs +++ b/smart_contracts/contracts/test/get-call-stack-recursive-subcall/src/main.rs @@ -37,7 +37,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let forwarder_session_entry_point = EntryPoint::new( METHOD_FORWARDER_SESSION_NAME.to_string(), @@ -47,7 +47,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(forwarder_contract_entry_point); entry_points.add_entry_point(forwarder_session_entry_point); diff --git a/smart_contracts/contracts/test/get-caller-subcall/src/main.rs b/smart_contracts/contracts/test/get-caller-subcall/src/main.rs index fa7de3a352..e559585af0 100644 --- a/smart_contracts/contracts/test/get-caller-subcall/src/main.rs +++ b/smart_contracts/contracts/test/get-caller-subcall/src/main.rs @@ -42,7 +42,7 @@ pub extern "C" fn call() { Vec::new(), CLType::ByteArray(32), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); entry_points diff --git a/smart_contracts/contracts/test/gh-1470-regression/src/bin/main.rs b/smart_contracts/contracts/test/gh-1470-regression/src/bin/main.rs index f7ab7ca8e3..80a8ce2570 100644 --- a/smart_contracts/contracts/test/gh-1470-regression/src/bin/main.rs +++ b/smart_contracts/contracts/test/gh-1470-regression/src/bin/main.rs @@ -61,7 +61,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Groups(vec![Group::new(GROUP_LABEL)]), - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( @@ -73,7 +73,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Groups(vec![Group::new(GROUP_LABEL)]), - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let named_keys = NamedKeys::new(); diff --git a/smart_contracts/contracts/test/gh-1688-regression/src/main.rs b/smart_contracts/contracts/test/gh-1688-regression/src/main.rs index d8d5db275b..f9b7ca0faa 100644 --- a/smart_contracts/contracts/test/gh-1688-regression/src/main.rs +++ b/smart_contracts/contracts/test/gh-1688-regression/src/main.rs @@ -30,7 +30,7 @@ fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let (contract_hash, _version) = storage::new_contract( diff --git a/smart_contracts/contracts/test/gh-2280-regression/src/main.rs b/smart_contracts/contracts/test/gh-2280-regression/src/main.rs index 64b24d0d19..ca01cafd3a 100644 --- a/smart_contracts/contracts/test/gh-2280-regression/src/main.rs +++ b/smart_contracts/contracts/test/gh-2280-regression/src/main.rs @@ -48,7 +48,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_TARGET, AccountHash::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(faucet_entrypoint); diff --git a/smart_contracts/contracts/test/gh-3097-regression/src/main.rs b/smart_contracts/contracts/test/gh-3097-regression/src/main.rs index c217ed700f..a8cf62cdc5 100644 --- a/smart_contracts/contracts/test/gh-3097-regression/src/main.rs +++ b/smart_contracts/contracts/test/gh-3097-regression/src/main.rs @@ -33,7 +33,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(do_something); diff --git a/smart_contracts/contracts/test/groups/src/main.rs b/smart_contracts/contracts/test/groups/src/main.rs index e609399a8f..d4eb57c69b 100644 --- a/smart_contracts/contracts/test/groups/src/main.rs +++ b/smart_contracts/contracts/test/groups/src/main.rs @@ -16,10 +16,9 @@ use casper_contract::{ }; use casper_types::{ addressable_entity::{EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, NamedKeys}, - package::ENTITY_INITIAL_VERSION, runtime_args, system::{handle_payment, standard_payment}, - CLType, CLTyped, Key, PackageHash, Parameter, RuntimeArgs, URef, U512, + CLType, CLTyped, Key, PackageHash, Parameter, RuntimeArgs, URef, ENTITY_INITIAL_VERSION, U512, }; const PACKAGE_HASH_KEY: &str = "package_hash_key"; @@ -132,7 +131,7 @@ fn create_entry_points_1() -> EntryPoints { Vec::new(), CLType::I32, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(restricted_session); @@ -141,7 +140,7 @@ fn create_entry_points_1() -> EntryPoints { Vec::new(), CLType::I32, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(restricted_contract); @@ -150,7 +149,7 @@ fn create_entry_points_1() -> EntryPoints { vec![Parameter::new(ARG_PACKAGE_HASH, CLType::Key)], CLType::I32, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(restricted_session_caller); @@ -159,7 +158,7 @@ fn create_entry_points_1() -> EntryPoints { Vec::new(), CLType::I32, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(restricted_contract); @@ -172,7 +171,7 @@ fn create_entry_points_1() -> EntryPoints { EntryPointAccess::Public, // NOTE: Public contract authorizes any contract call, because this contract has groups // uref in its named keys - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(unrestricted_contract_caller); @@ -185,7 +184,7 @@ fn create_entry_points_1() -> EntryPoints { EntryPointAccess::Public, // NOTE: Public contract authorizes any contract call, because this contract has groups // uref in its named keys - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(unrestricted_contract_caller_as_session); @@ -198,7 +197,7 @@ fn create_entry_points_1() -> EntryPoints { EntryPointAccess::groups(&[]), // NOTE: Public contract authorizes any contract call, because this contract has groups // uref in its named keys - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(uncallable_session); @@ -211,7 +210,7 @@ fn create_entry_points_1() -> EntryPoints { EntryPointAccess::groups(&[]), // NOTE: Public contract authorizes any contract call, because this contract has groups // uref in its named keys - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(uncallable_contract); @@ -226,7 +225,7 @@ fn create_entry_points_1() -> EntryPoints { EntryPointAccess::Public, // NOTE: Public contract authorizes any contract call, because this contract has groups // uref in its named keys - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(call_restricted_entry_points); @@ -238,7 +237,7 @@ fn create_entry_points_1() -> EntryPoints { )], CLType::Unit, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(restricted_standard_payment); diff --git a/smart_contracts/contracts/test/host-function-costs/src/main.rs b/smart_contracts/contracts/test/host-function-costs/src/main.rs index 08ab3c97cd..e1930a2c7c 100644 --- a/smart_contracts/contracts/test/host-function-costs/src/main.rs +++ b/smart_contracts/contracts/test/host-function-costs/src/main.rs @@ -281,7 +281,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -290,7 +290,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -299,7 +299,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -307,7 +307,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -316,7 +316,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -324,7 +324,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -333,7 +333,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -341,7 +341,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -350,7 +350,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_BYTES, >::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -359,7 +359,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -368,7 +368,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -377,7 +377,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -386,7 +386,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/manage-groups/src/main.rs b/smart_contracts/contracts/test/manage-groups/src/main.rs index 5d38556636..50f93921a8 100644 --- a/smart_contracts/contracts/test/manage-groups/src/main.rs +++ b/smart_contracts/contracts/test/manage-groups/src/main.rs @@ -178,7 +178,7 @@ fn create_entry_points_1() -> EntryPoints { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(restricted_session); @@ -187,7 +187,7 @@ fn create_entry_points_1() -> EntryPoints { vec![Parameter::new(GROUP_NAME_ARG, CLType::String)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(remove_group); @@ -200,7 +200,7 @@ fn create_entry_points_1() -> EntryPoints { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(extend_group_urefs); @@ -213,7 +213,7 @@ fn create_entry_points_1() -> EntryPoints { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(remove_group_urefs); entry_points diff --git a/smart_contracts/contracts/test/measure-gas-subcall/src/main.rs b/smart_contracts/contracts/test/measure-gas-subcall/src/main.rs index c49a21eb71..e44dbb2617 100644 --- a/smart_contracts/contracts/test/measure-gas-subcall/src/main.rs +++ b/smart_contracts/contracts/test/measure-gas-subcall/src/main.rs @@ -44,7 +44,7 @@ fn store() -> (AddressableEntityHash, EntityVersion) { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_1); @@ -54,7 +54,7 @@ fn store() -> (AddressableEntityHash, EntityVersion) { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point_2); diff --git a/smart_contracts/contracts/test/multisig-authorization/src/main.rs b/smart_contracts/contracts/test/multisig-authorization/src/main.rs index 456ec24e39..a085778d50 100644 --- a/smart_contracts/contracts/test/multisig-authorization/src/main.rs +++ b/smart_contracts/contracts/test/multisig-authorization/src/main.rs @@ -77,7 +77,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let entrypoint_b = EntryPoint::new( @@ -85,7 +85,7 @@ pub extern "C" fn call() { Parameters::default(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entrypoint_a); diff --git a/smart_contracts/contracts/test/named-keys-stored/src/main.rs b/smart_contracts/contracts/test/named-keys-stored/src/main.rs index 348f7deba4..d54e7d8313 100644 --- a/smart_contracts/contracts/test/named-keys-stored/src/main.rs +++ b/smart_contracts/contracts/test/named-keys-stored/src/main.rs @@ -142,7 +142,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(contract_entrypoint); let session_entrypoint = EntryPoint::new( @@ -150,7 +150,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(session_entrypoint); let contract_to_contract_entrypoint = EntryPoint::new( @@ -158,7 +158,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(contract_to_contract_entrypoint); let contract_to_contract_entrypoint = EntryPoint::new( @@ -166,7 +166,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(contract_to_contract_entrypoint); entry_points diff --git a/smart_contracts/contracts/test/ordered-transforms/src/main.rs b/smart_contracts/contracts/test/ordered-transforms/src/main.rs index f7fa05e75d..7b565b10c4 100644 --- a/smart_contracts/contracts/test/ordered-transforms/src/main.rs +++ b/smart_contracts/contracts/test/ordered-transforms/src/main.rs @@ -25,7 +25,7 @@ pub extern "C" fn call() { )], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let n: u32 = runtime::get_named_arg("n"); diff --git a/smart_contracts/contracts/test/purse-holder-stored-upgrader/src/main.rs b/smart_contracts/contracts/test/purse-holder-stored-upgrader/src/main.rs index 4306526a85..7febdcae82 100644 --- a/smart_contracts/contracts/test/purse-holder-stored-upgrader/src/main.rs +++ b/smart_contracts/contracts/test/purse-holder-stored-upgrader/src/main.rs @@ -63,7 +63,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE_NAME, CLType::String)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(add); let version = EntryPoint::new( @@ -71,7 +71,7 @@ pub extern "C" fn call() { vec![], CLType::String, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(version); @@ -80,7 +80,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE_NAME, CLType::String)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(remove); entry_points diff --git a/smart_contracts/contracts/test/purse-holder-stored/src/main.rs b/smart_contracts/contracts/test/purse-holder-stored/src/main.rs index df60cff72a..6a2cf6f6e0 100644 --- a/smart_contracts/contracts/test/purse-holder-stored/src/main.rs +++ b/smart_contracts/contracts/test/purse-holder-stored/src/main.rs @@ -52,7 +52,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE, CLType::String)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(add); let version = EntryPoint::new( @@ -60,7 +60,7 @@ pub extern "C" fn call() { vec![], CLType::String, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(version); entry_points diff --git a/smart_contracts/contracts/test/regression-20210707/src/main.rs b/smart_contracts/contracts/test/regression-20210707/src/main.rs index 33356e03f3..820ebe1082 100644 --- a/smart_contracts/contracts/test/regression-20210707/src/main.rs +++ b/smart_contracts/contracts/test/regression-20210707/src/main.rs @@ -149,7 +149,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let send_to_purse = EntryPoint::new( METHOD_SEND_TO_PURSE, @@ -160,7 +160,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let hardcoded_src = EntryPoint::new( METHOD_HARDCODED_PURSE_SRC, @@ -170,7 +170,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let stored_payment = EntryPoint::new( METHOD_STORED_PAYMENT, @@ -180,14 +180,14 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let hardcoded_payment = EntryPoint::new( METHOD_HARDCODED_PAYMENT, vec![Parameter::new(ARG_AMOUNT, CLType::U512)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(send_to_account); diff --git a/smart_contracts/contracts/test/regression-20210831/src/main.rs b/smart_contracts/contracts/test/regression-20210831/src/main.rs index 9d3209575b..80b6a4b945 100644 --- a/smart_contracts/contracts/test/regression-20210831/src/main.rs +++ b/smart_contracts/contracts/test/regression-20210831/src/main.rs @@ -85,10 +85,10 @@ fn forwarded_undelegate_args() -> RuntimeArgs { } fn forwarded_activate_bid_args() -> RuntimeArgs { - let validator_public_key: PublicKey = runtime::get_named_arg(auction::ARG_VALIDATOR_PUBLIC_KEY); + let validator_public_key: PublicKey = runtime::get_named_arg(auction::ARG_VALIDATOR); runtime_args! { - auction::ARG_VALIDATOR_PUBLIC_KEY => validator_public_key, + auction::ARG_VALIDATOR => validator_public_key, } } @@ -182,7 +182,7 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(add_bid_proxy_call_1); @@ -195,7 +195,7 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(add_bid_proxy_call); @@ -207,7 +207,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let withdraw_proxy_call = EntryPoint::new( @@ -218,7 +218,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let delegate_proxy_call = EntryPoint::new( @@ -230,7 +230,7 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let delegate_proxy_call_1 = EntryPoint::new( @@ -242,7 +242,7 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let undelegate_proxy_call = EntryPoint::new( @@ -254,7 +254,7 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let undelegate_proxy_call_1 = EntryPoint::new( @@ -266,28 +266,22 @@ pub extern "C" fn call() { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let activate_bid_proxy_call = EntryPoint::new( METHOD_ACTIVATE_BID_CALL, - vec![Parameter::new( - auction::ARG_VALIDATOR_PUBLIC_KEY, - CLType::PublicKey, - )], + vec![Parameter::new(auction::ARG_VALIDATOR, CLType::PublicKey)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); let activate_bid_proxy_call_1 = EntryPoint::new( METHOD_ACTIVATE_BID_CALL_1, - vec![Parameter::new( - auction::ARG_VALIDATOR_PUBLIC_KEY, - CLType::PublicKey, - )], + vec![Parameter::new(auction::ARG_VALIDATOR, CLType::PublicKey)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(withdraw_proxy_call); diff --git a/smart_contracts/contracts/test/regression-20220204/src/main.rs b/smart_contracts/contracts/test/regression-20220204/src/main.rs index d541c5cde1..e3e3fb547d 100644 --- a/smart_contracts/contracts/test/regression-20220204/src/main.rs +++ b/smart_contracts/contracts/test/regression-20220204/src/main.rs @@ -34,7 +34,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE, URef::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); type NonTrivialArg = BTreeMap; @@ -44,7 +44,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_PURSE, NonTrivialArg::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let named_keys = { diff --git a/smart_contracts/contracts/test/regression-20220211/src/main.rs b/smart_contracts/contracts/test/regression-20220211/src/main.rs index 6ca1cf5950..4aacb2c37f 100644 --- a/smart_contracts/contracts/test/regression-20220211/src/main.rs +++ b/smart_contracts/contracts/test/regression-20220211/src/main.rs @@ -30,7 +30,7 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( @@ -38,63 +38,63 @@ pub extern "C" fn call() { Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( PUT_KEY_AS_SESSION, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( PUT_KEY_AS_CONTRACT, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( READ_AS_SESSION, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( READ_AS_CONTRACT, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( WRITE_AS_SESSION, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( WRITE_AS_CONTRACT, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( ADD_AS_SESSION, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); entry_points.add_entry_point(EntryPoint::new( ADD_AS_CONTRACT, Parameters::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let (contract_hash, _contract_version) = storage::new_locked_contract(entry_points, None, None, None, None); diff --git a/smart_contracts/contracts/test/regression_20211110/src/main.rs b/smart_contracts/contracts/test/regression_20211110/src/main.rs index 8e16815e05..5f1d793f4a 100644 --- a/smart_contracts/contracts/test/regression_20211110/src/main.rs +++ b/smart_contracts/contracts/test/regression_20211110/src/main.rs @@ -22,7 +22,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_TARGET, AddressableEntityHash::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let (contract_hash, _contract_version) = diff --git a/smart_contracts/contracts/test/ret-uref/src/main.rs b/smart_contracts/contracts/test/ret-uref/src/main.rs index 2b6bc38392..09b9e8d8e3 100644 --- a/smart_contracts/contracts/test/ret-uref/src/main.rs +++ b/smart_contracts/contracts/test/ret-uref/src/main.rs @@ -54,7 +54,7 @@ pub extern "C" fn call() { vec![Parameter::new(ACCESS_UREF, CLType::URef)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(put_uref_entrypoint); let get_uref_entrypoint = EntryPoint::new( @@ -62,7 +62,7 @@ pub extern "C" fn call() { vec![], CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(get_uref_entrypoint); let insert_uref_entrypoint = EntryPoint::new( @@ -70,7 +70,7 @@ pub extern "C" fn call() { vec![Parameter::new("contract_hash", CLType::ByteArray(32))], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(insert_uref_entrypoint); entry_points diff --git a/smart_contracts/contracts/test/storage-costs/src/main.rs b/smart_contracts/contracts/test/storage-costs/src/main.rs index d713cc7c4a..e665c6f874 100644 --- a/smart_contracts/contracts/test/storage-costs/src/main.rs +++ b/smart_contracts/contracts/test/storage-costs/src/main.rs @@ -143,7 +143,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -151,7 +151,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -159,7 +159,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( @@ -167,7 +167,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -176,7 +176,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -185,7 +185,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -194,7 +194,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -203,7 +203,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -212,7 +212,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -221,7 +221,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -230,7 +230,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -239,7 +239,7 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/smart_contracts/contracts/test/test-payment-stored/src/main.rs b/smart_contracts/contracts/test/test-payment-stored/src/main.rs index be81984d8e..24eddf3bd7 100644 --- a/smart_contracts/contracts/test/test-payment-stored/src/main.rs +++ b/smart_contracts/contracts/test/test-payment-stored/src/main.rs @@ -53,7 +53,7 @@ pub extern "C" fn call() { vec![Parameter::new(standard_payment::ARG_AMOUNT, CLType::U512)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); entry_points diff --git a/smart_contracts/contracts/test/transfer-purse-to-account-stored/src/main.rs b/smart_contracts/contracts/test/transfer-purse-to-account-stored/src/main.rs index fe562fe2f6..b46127963b 100644 --- a/smart_contracts/contracts/test/transfer-purse-to-account-stored/src/main.rs +++ b/smart_contracts/contracts/test/transfer-purse-to-account-stored/src/main.rs @@ -38,7 +38,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(entry_point); entry_points diff --git a/smart_contracts/contracts/test/transfer-purse-to-accounts-stored/src/main.rs b/smart_contracts/contracts/test/transfer-purse-to-accounts-stored/src/main.rs index 3f1b884d3a..dcbbc0c3d1 100644 --- a/smart_contracts/contracts/test/transfer-purse-to-accounts-stored/src/main.rs +++ b/smart_contracts/contracts/test/transfer-purse-to-accounts-stored/src/main.rs @@ -56,7 +56,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); tmp.add_entry_point(entry_point); tmp diff --git a/smart_contracts/contracts/test/upgrade-threshold-upgrader/src/main.rs b/smart_contracts/contracts/test/upgrade-threshold-upgrader/src/main.rs index edf56742eb..35e165dfdc 100644 --- a/smart_contracts/contracts/test/upgrade-threshold-upgrader/src/main.rs +++ b/smart_contracts/contracts/test/upgrade-threshold-upgrader/src/main.rs @@ -57,7 +57,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entrypoints.add_entry_point(add_associated_key_entry_point); let manage_action_threshold_entrypoint = EntryPoint::new( @@ -65,7 +65,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_NEW_UPGRADE_THRESHOLD, CLType::U8)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entrypoints.add_entry_point(manage_action_threshold_entrypoint); let remove_associated_key_entry_point = EntryPoint::new( @@ -76,7 +76,7 @@ pub extern "C" fn call() { )], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entrypoints.add_entry_point(remove_associated_key_entry_point); entrypoints diff --git a/smart_contracts/contracts/test/upgrade-threshold/src/main.rs b/smart_contracts/contracts/test/upgrade-threshold/src/main.rs index e73d3f5f91..8270ac0de3 100644 --- a/smart_contracts/contracts/test/upgrade-threshold/src/main.rs +++ b/smart_contracts/contracts/test/upgrade-threshold/src/main.rs @@ -51,7 +51,7 @@ pub extern "C" fn call() { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entrypoints.add_entry_point(add_associated_key_entry_point); let manage_action_threshold_entrypoint = EntryPoint::new( @@ -59,7 +59,7 @@ pub extern "C" fn call() { vec![Parameter::new(ARG_NEW_UPGRADE_THRESHOLD, CLType::U8)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entrypoints.add_entry_point(manage_action_threshold_entrypoint); entrypoints diff --git a/smart_contracts/contracts/tutorial/counter-installer/src/main.rs b/smart_contracts/contracts/tutorial/counter-installer/src/main.rs index 4448bd8504..8c4dc9b364 100644 --- a/smart_contracts/contracts/tutorial/counter-installer/src/main.rs +++ b/smart_contracts/contracts/tutorial/counter-installer/src/main.rs @@ -65,14 +65,14 @@ pub extern "C" fn call() { Vec::new(), CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); counter_entry_points.add_entry_point(EntryPoint::new( COUNTER_GET, Vec::new(), CLType::I32, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, )); let (stored_contract_hash, contract_version) = storage::new_contract( diff --git a/storage/README.md b/storage/README.md index 53433e99f6..cbcd18a26a 100644 --- a/storage/README.md +++ b/storage/README.md @@ -1,10 +1,10 @@ -# `casper-hashing` +# `casper-storage` [![LOGO](https://raw.githubusercontent.com/casper-network/casper-node/master/images/casper-association-logo-primary.svg)](https://casper.network/) [![Build Status](https://drone-auto-casper-network.casperlabs.io/api/badges/casper-network/casper-node/status.svg?branch=dev)](http://drone-auto-casper-network.casperlabs.io/casper-network/casper-node) -[![Crates.io](https://img.shields.io/crates/v/casper-hashing)](https://crates.io/crates/casper-hashing) -[![Documentation](https://docs.rs/casper-hashing/badge.svg)](https://docs.rs/casper-hashing) +[![Crates.io](https://img.shields.io/crates/v/casper-hashing)](https://crates.io/crates/casper-storage) +[![Documentation](https://docs.rs/casper-hashing/badge.svg)](https://docs.rs/casper-storage) [![License](https://img.shields.io/badge/license-Apache-blue)](https://github.com/CasperLabs/casper-node/blob/master/LICENSE) A library providing storage functionality for Casper nodes. diff --git a/storage/src/block_store/lmdb/indexed_lmdb_block_store.rs b/storage/src/block_store/lmdb/indexed_lmdb_block_store.rs index d275f4591d..4cc4c73280 100644 --- a/storage/src/block_store/lmdb/indexed_lmdb_block_store.rs +++ b/storage/src/block_store/lmdb/indexed_lmdb_block_store.rs @@ -3,7 +3,9 @@ use std::{ collections::{btree_map, hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet}, }; -use super::{lmdb_block_store::LmdbBlockStore, lmdb_ext::LmdbExtError, temp_map::TempMap}; +use super::{ + lmdb_block_store::LmdbBlockStore, lmdb_ext::LmdbExtError, temp_map::TempMap, DbTableId, +}; use datasize::DataSize; use lmdb::{ Environment, RoTransaction, RwCursor, RwTransaction, Transaction as LmdbTransaction, WriteFlags, @@ -18,13 +20,11 @@ use crate::block_store::{ ApprovalsHashes, BlockExecutionResults, BlockHashHeightAndEra, BlockHeight, BlockTransfers, LatestSwitchBlock, StateStore, StateStoreKey, Tip, TransactionFinalizedApprovals, }, - BlockStoreError, BlockStoreProvider, + BlockStoreError, BlockStoreProvider, DbRawBytesSpec, }; use casper_types::{ - binary_port::{DbRawBytesSpec, RecordId}, - execution::ExecutionResult, - Approval, Block, BlockBody, BlockHash, BlockHeader, BlockSignatures, Digest, EraId, - ProtocolVersion, Transaction, TransactionHash, Transfer, + execution::ExecutionResult, Approval, Block, BlockBody, BlockHash, BlockHeader, + BlockSignatures, Digest, EraId, ProtocolVersion, Transaction, TransactionHash, Transfer, }; #[derive(DataSize, Debug)] @@ -336,15 +336,15 @@ fn initialize_execution_result_dbs( info!("execution result databases initialized"); Ok(()) } -pub struct IndexedLmdbBlockStoreRWTransaction<'a> { - txn: RwTransaction<'a>, - block_store: &'a LmdbBlockStore, - block_height_index: TempMap<'a, u64, BlockHash>, - switch_block_era_id_index: TempMap<'a, EraId, BlockHash>, - transaction_hash_index: TempMap<'a, TransactionHash, BlockHashHeightAndEra>, +pub struct IndexedLmdbBlockStoreRWTransaction<'t> { + txn: RwTransaction<'t>, + block_store: &'t LmdbBlockStore, + block_height_index: TempMap<'t, u64, BlockHash>, + switch_block_era_id_index: TempMap<'t, EraId, BlockHash>, + transaction_hash_index: TempMap<'t, TransactionHash, BlockHashHeightAndEra>, } -impl<'a> IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> IndexedLmdbBlockStoreRWTransaction<'t> { /// Check if the block height index can be updated. fn should_update_block_height_index( &self, @@ -419,9 +419,9 @@ impl<'a> IndexedLmdbBlockStoreRWTransaction<'a> { } } -pub struct IndexedLmdbBlockStoreReadTransaction<'a> { - txn: RoTransaction<'a>, - block_store: &'a IndexedLmdbBlockStore, +pub struct IndexedLmdbBlockStoreReadTransaction<'t> { + txn: RoTransaction<'t>, + block_store: &'t IndexedLmdbBlockStore, } enum LmdbBlockStoreIndex { @@ -441,7 +441,7 @@ enum DataType { BlockSignatures, } -impl<'a> IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> IndexedLmdbBlockStoreReadTransaction<'t> { fn block_hash_from_index(&self, index: LmdbBlockStoreIndex) -> Option<&BlockHash> { match index { LmdbBlockStoreIndex::BlockHeight(position) => match position { @@ -540,7 +540,7 @@ impl<'a> IndexedLmdbBlockStoreReadTransaction<'a> { } } -impl<'a> BlockStoreTransaction for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> BlockStoreTransaction for IndexedLmdbBlockStoreReadTransaction<'t> { fn commit(self) -> Result<(), BlockStoreError> { Ok(()) } @@ -550,7 +550,7 @@ impl<'a> BlockStoreTransaction for IndexedLmdbBlockStoreReadTransaction<'a> { } } -impl<'a> BlockStoreTransaction for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> BlockStoreTransaction for IndexedLmdbBlockStoreRWTransaction<'t> { fn commit(self) -> Result<(), BlockStoreError> { self.txn .commit() @@ -568,8 +568,8 @@ impl<'a> BlockStoreTransaction for IndexedLmdbBlockStoreRWTransaction<'a> { } impl BlockStoreProvider for IndexedLmdbBlockStore { - type Reader<'a> = IndexedLmdbBlockStoreReadTransaction<'a>; - type ReaderWriter<'a> = IndexedLmdbBlockStoreRWTransaction<'a>; + type Reader<'t> = IndexedLmdbBlockStoreReadTransaction<'t>; + type ReaderWriter<'t> = IndexedLmdbBlockStoreRWTransaction<'t>; fn checkout_ro(&self) -> Result, BlockStoreError> { self.get_reader() @@ -592,7 +592,7 @@ impl BlockStoreProvider for IndexedLmdbBlockStore { } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -604,7 +604,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<' } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -618,7 +618,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransac } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -632,7 +632,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTra } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -646,7 +646,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTra } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHeight) -> Result, BlockStoreError> { self.read_block_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Key(key))) } @@ -659,7 +659,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHeight) -> Result, BlockStoreError> { self.read_block_header_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Key(key))) } @@ -672,7 +672,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTrans } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHeight) -> Result, BlockStoreError> { self.read_approvals_hashes_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Key( key, @@ -687,7 +687,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadT } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: BlockHeight) -> Result, BlockStoreError> { self.read_block_signatures_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Key( key, @@ -703,7 +703,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadT } /// Retrieves single switch block by era ID by looking it up in the index and returning it. -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: EraId) -> Result, BlockStoreError> { self.read_block_indexed(LmdbBlockStoreIndex::SwitchBlockEraId(IndexPosition::Key( key, @@ -720,7 +720,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { /// Retrieves single switch block header by era ID by looking it up in the index and returning /// it. -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: EraId) -> Result, BlockStoreError> { self.read_block_header_indexed(LmdbBlockStoreIndex::SwitchBlockEraId(IndexPosition::Key( key, @@ -735,7 +735,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: EraId) -> Result, BlockStoreError> { self.read_approvals_hashes_indexed(LmdbBlockStoreIndex::SwitchBlockEraId( IndexPosition::Key(key), @@ -750,7 +750,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransac } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: EraId) -> Result, BlockStoreError> { self.read_block_signatures_indexed(LmdbBlockStoreIndex::SwitchBlockEraId( IndexPosition::Key(key), @@ -765,7 +765,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransac } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, _key: Tip) -> Result, BlockStoreError> { self.read_block_header_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Tip)) } @@ -778,7 +778,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<' } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, _key: Tip) -> Result, BlockStoreError> { self.read_block_indexed(LmdbBlockStoreIndex::BlockHeight(IndexPosition::Tip)) } @@ -791,7 +791,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, _key: LatestSwitchBlock) -> Result, BlockStoreError> { self.read_block_header_indexed(LmdbBlockStoreIndex::SwitchBlockEraId(IndexPosition::Tip)) } @@ -804,8 +804,8 @@ impl<'a> DataReader for IndexedLmdbBlockStoreRea } } -impl<'a> DataReader - for IndexedLmdbBlockStoreReadTransaction<'a> +impl<'t> DataReader + for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: TransactionHash) -> Result, BlockStoreError> { Ok(self.block_store.transaction_hash_index.get(&key).copied()) @@ -816,7 +816,7 @@ impl<'a> DataReader } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: TransactionHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -832,8 +832,8 @@ impl<'a> DataReader for IndexedLmdbBlockStoreReadT } } -impl<'a> DataReader> - for IndexedLmdbBlockStoreReadTransaction<'a> +impl<'t> DataReader> + for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: TransactionHash) -> Result>, BlockStoreError> { self.block_store @@ -852,7 +852,7 @@ impl<'a> DataReader> } } -impl<'a> DataReader for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, key: TransactionHash) -> Result, BlockStoreError> { self.block_store .block_store @@ -870,7 +870,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreR } } -impl<'a> DataReader> for IndexedLmdbBlockStoreReadTransaction<'a> { +impl<'t> DataReader> for IndexedLmdbBlockStoreReadTransaction<'t> { fn read(&self, StateStoreKey(key): StateStoreKey) -> Result>, BlockStoreError> { self.block_store .block_store @@ -884,39 +884,35 @@ impl<'a> DataReader> for IndexedLmdbBlockStoreReadTransac } } -impl<'a> DataReader<(RecordId, Vec), DbRawBytesSpec> - for IndexedLmdbBlockStoreReadTransaction<'a> +impl<'t> DataReader<(DbTableId, Vec), DbRawBytesSpec> + for IndexedLmdbBlockStoreReadTransaction<'t> { fn read( &self, - (id, key): (RecordId, Vec), + (id, key): (DbTableId, Vec), ) -> Result, BlockStoreError> { let store = &self.block_store.block_store; let res = match id { - RecordId::BlockHeader => store.block_header_dbs.get_raw(&self.txn, &key), - RecordId::BlockBody => store.block_body_dbs.get_raw(&self.txn, &key), - RecordId::ApprovalsHashes => store.approvals_hashes_dbs.get_raw(&self.txn, &key), - RecordId::BlockMetadata => store.block_metadata_dbs.get_raw(&self.txn, &key), - RecordId::Transaction => store.transaction_dbs.get_raw(&self.txn, &key), - RecordId::ExecutionResult => store.execution_result_dbs.get_raw(&self.txn, &key), - RecordId::Transfer => match self.txn.get(store.transfer_db, &key) { - Ok(bytes) => Ok(Some(DbRawBytesSpec::new_legacy(bytes))), - Err(lmdb::Error::NotFound) => Ok(None), - Err(err) => return Err(BlockStoreError::InternalStorage(Box::new(err))), - }, - RecordId::FinalizedTransactionApprovals => store + DbTableId::BlockHeader => store.block_header_dbs.get_raw(&self.txn, &key), + DbTableId::BlockBody => store.block_body_dbs.get_raw(&self.txn, &key), + DbTableId::ApprovalsHashes => store.approvals_hashes_dbs.get_raw(&self.txn, &key), + DbTableId::BlockMetadata => store.block_metadata_dbs.get_raw(&self.txn, &key), + DbTableId::Transaction => store.transaction_dbs.get_raw(&self.txn, &key), + DbTableId::ExecutionResult => store.execution_result_dbs.get_raw(&self.txn, &key), + DbTableId::Transfer => store.transfer_dbs.get_raw(&self.txn, &key), + DbTableId::FinalizedTransactionApprovals => store .finalized_transaction_approvals_dbs .get_raw(&self.txn, &key), }; res.map_err(|err| BlockStoreError::InternalStorage(Box::new(err))) } - fn exists(&mut self, key: (RecordId, Vec)) -> Result { + fn exists(&mut self, key: (DbTableId, Vec)) -> Result { self.read(key).map(|res| res.is_some()) } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { /// Writes a block to storage. /// /// Returns `Ok(true)` if the block has been successfully written, `Ok(false)` if a part of it @@ -999,7 +995,7 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &ApprovalsHashes) -> Result { self.block_store.write_approvals_hashes(&mut self.txn, data) } @@ -1010,7 +1006,7 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTrans } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &BlockSignatures) -> Result { self.block_store .write_finality_signatures(&mut self.txn, data) @@ -1022,7 +1018,7 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTrans } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &BlockHeader) -> Result { let block_hash = data.block_hash(); let block_height = data.height(); @@ -1061,7 +1057,7 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransacti } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &Transaction) -> Result { self.block_store.write_transaction(&mut self.txn, data) } @@ -1071,8 +1067,8 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTra } } -impl<'a> DataWriter - for IndexedLmdbBlockStoreRWTransaction<'a> +impl<'t> DataWriter + for IndexedLmdbBlockStoreRWTransaction<'t> { fn write( &mut self, @@ -1098,8 +1094,8 @@ impl<'a> DataWriter } } -impl<'a> DataWriter - for IndexedLmdbBlockStoreRWTransaction<'a> +impl<'t> DataWriter + for IndexedLmdbBlockStoreRWTransaction<'t> { fn write( &mut self, @@ -1136,7 +1132,7 @@ impl<'a> DataWriter } } -impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &BlockTransfers) -> Result { self.block_store .write_transfers(&mut self.txn, &data.block_hash, &data.transfers) @@ -1148,7 +1144,7 @@ impl<'a> DataWriter for IndexedLmdbBlockStoreRWTransa } } -impl<'a> DataWriter, StateStore> for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataWriter, StateStore> for IndexedLmdbBlockStoreRWTransaction<'t> { fn write(&mut self, data: &StateStore) -> Result, BlockStoreError> { self.block_store .write_state_store(&mut self.txn, data.key.clone(), &data.value)?; @@ -1160,7 +1156,7 @@ impl<'a> DataWriter, StateStore> for IndexedLmdbBlockStoreRWT } } -impl<'a> DataReader for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, query: TransactionHash) -> Result, BlockStoreError> { self.block_store .transaction_dbs @@ -1173,7 +1169,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreRWTra } } -impl<'a> DataReader for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store.get_block_signatures(&self.txn, &key) } @@ -1183,8 +1179,8 @@ impl<'a> DataReader for IndexedLmdbBlockStoreRWTrans } } -impl<'a> DataReader> - for IndexedLmdbBlockStoreRWTransaction<'a> +impl<'t> DataReader> + for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, query: TransactionHash) -> Result>, BlockStoreError> { self.block_store @@ -1201,7 +1197,7 @@ impl<'a> DataReader> } } -impl<'a> DataReader for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, key: BlockHash) -> Result, BlockStoreError> { self.block_store.get_single_block(&self.txn, &key) } @@ -1211,7 +1207,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreRWTransaction<'a> } } -impl<'a> DataReader for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataReader for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, query: TransactionHash) -> Result, BlockStoreError> { self.block_store .execution_result_dbs @@ -1227,7 +1223,7 @@ impl<'a> DataReader for IndexedLmdbBlockStoreR } } -impl<'a> DataReader> for IndexedLmdbBlockStoreRWTransaction<'a> { +impl<'t> DataReader> for IndexedLmdbBlockStoreRWTransaction<'t> { fn read(&self, key: BlockHash) -> Result>, BlockStoreError> { self.block_store.get_transfers(&self.txn, &key) } diff --git a/storage/src/block_store/lmdb/lmdb_block_store.rs b/storage/src/block_store/lmdb/lmdb_block_store.rs index d2c171c84d..799ff71dce 100644 --- a/storage/src/block_store/lmdb/lmdb_block_store.rs +++ b/storage/src/block_store/lmdb/lmdb_block_store.rs @@ -1,17 +1,3 @@ -use super::lmdb_ext::{LmdbExtError, TransactionExt, WriteTransactionExt}; -use crate::block_store::{ - error::BlockStoreError, - types::{ - BlockExecutionResults, BlockHashHeightAndEra, BlockTransfers, StateStore, - TransactionFinalizedApprovals, - }, - BlockStoreProvider, BlockStoreTransaction, DataReader, DataWriter, -}; -use datasize::DataSize; -use lmdb::{ - Database, DatabaseFlags, Environment, EnvironmentFlags, RoTransaction, RwTransaction, - Transaction as LmdbTransaction, WriteFlags, -}; use std::{ borrow::Cow, collections::{BTreeSet, HashMap}, @@ -19,16 +5,30 @@ use std::{ sync::Arc, }; +use datasize::DataSize; use tracing::{debug, error}; -use super::versioned_databases::VersionedDatabases; -use crate::block_store::types::ApprovalsHashes; use casper_types::{ - execution::{ - execution_result_v1, ExecutionResult, ExecutionResultV1, ExecutionResultV2, TransformKindV2, + execution::{execution_result_v1, ExecutionResult, ExecutionResultV1, ExecutionResultV2}, + Approval, Block, BlockBody, BlockHash, BlockHeader, BlockSignatures, Digest, Transaction, + TransactionHash, Transfer, +}; + +use super::{ + lmdb_ext::{LmdbExtError, TransactionExt}, + versioned_databases::VersionedDatabases, +}; +use crate::block_store::{ + error::BlockStoreError, + types::{ + ApprovalsHashes, BlockExecutionResults, BlockHashHeightAndEra, BlockTransfers, StateStore, + TransactionFinalizedApprovals, Transfers, }, - Approval, Block, BlockBody, BlockHash, BlockHeader, BlockSignatures, Digest, StoredValue, - Transaction, TransactionHash, Transfer, + BlockStoreProvider, BlockStoreTransaction, DataReader, DataWriter, +}; +use lmdb::{ + Database, DatabaseFlags, Environment, EnvironmentFlags, RoTransaction, RwTransaction, + Transaction as LmdbTransaction, WriteFlags, }; /// Filename for the LMDB database created by the Storage component. @@ -39,7 +39,7 @@ const STORAGE_DB_FILENAME: &str = "storage.lmdb"; const MAX_TRANSACTIONS: u32 = 5; /// Maximum number of allowed dbs. -const MAX_DB_COUNT: u32 = 16; +const MAX_DB_COUNT: u32 = 17; /// OS-specific lmdb flags. #[cfg(not(target_os = "macos"))] @@ -57,28 +57,27 @@ pub struct LmdbBlockStore { root: PathBuf, /// Environment holding LMDB databases. #[data_size(skip)] - pub(crate) env: Arc, + pub(super) env: Arc, /// The block header databases. - pub(crate) block_header_dbs: VersionedDatabases, + pub(super) block_header_dbs: VersionedDatabases, /// The block body databases. - pub(crate) block_body_dbs: VersionedDatabases, + pub(super) block_body_dbs: VersionedDatabases, /// The approvals hashes databases. - pub(crate) approvals_hashes_dbs: VersionedDatabases, + pub(super) approvals_hashes_dbs: VersionedDatabases, /// The block metadata db. - pub(crate) block_metadata_dbs: VersionedDatabases, + pub(super) block_metadata_dbs: VersionedDatabases, /// The transaction databases. - pub(crate) transaction_dbs: VersionedDatabases, + pub(super) transaction_dbs: VersionedDatabases, /// Databases of `ExecutionResult`s indexed by transaction hash for current DB or by deploy /// hash for legacy DB. - pub(crate) execution_result_dbs: VersionedDatabases, - /// The transfer database. - #[data_size(skip)] - pub(crate) transfer_db: Database, + pub(super) execution_result_dbs: VersionedDatabases, + /// The transfer databases. + pub(super) transfer_dbs: VersionedDatabases, /// The state storage database. #[data_size(skip)] state_store_db: Database, /// The finalized transaction approvals databases. - pub(crate) finalized_transaction_approvals_dbs: + pub(super) finalized_transaction_approvals_dbs: VersionedDatabases>, } @@ -100,8 +99,7 @@ impl LmdbBlockStore { let execution_result_dbs = VersionedDatabases::new(&env, "deploy_metadata", "execution_results") .map_err(|err| BlockStoreError::InternalStorage(Box::new(err)))?; - let transfer_db = env - .create_db(Some("transfer"), DatabaseFlags::empty()) + let transfer_dbs = VersionedDatabases::new(&env, "transfer", "versioned_transfers") .map_err(|err| BlockStoreError::InternalStorage(Box::new(err)))?; let state_store_db = env .create_db(Some("state_store"), DatabaseFlags::empty()) @@ -123,7 +121,7 @@ impl LmdbBlockStore { block_metadata_dbs, transaction_dbs, execution_result_dbs, - transfer_db, + transfer_dbs, state_store_db, finalized_transaction_approvals_dbs, }) @@ -196,8 +194,11 @@ impl LmdbBlockStore { txn: &Tx, block_hash: &BlockHash, ) -> Result>, BlockStoreError> { - txn.get_value::<_, Vec>(self.transfer_db, block_hash) - .map_err(|err| BlockStoreError::InternalStorage(Box::new(err))) + Ok(self + .transfer_dbs + .get(txn, block_hash) + .map_err(|err| BlockStoreError::InternalStorage(Box::new(err)))? + .map(Transfers::into_owned)) } pub(crate) fn has_transfers( @@ -205,7 +206,8 @@ impl LmdbBlockStore { txn: &Tx, block_hash: &BlockHash, ) -> Result { - txn.value_exists(self.transfer_db, block_hash) + self.transfer_dbs + .exists(txn, block_hash) .map_err(|err| BlockStoreError::InternalStorage(Box::new(err))) } @@ -270,9 +272,15 @@ impl LmdbBlockStore { &self, txn: &mut RwTransaction, block_hash: &BlockHash, - transfers: &Vec, + transfers: &[Transfer], ) -> Result { - txn.put_value(self.transfer_db, block_hash, transfers, true) + self.transfer_dbs + .put( + txn, + block_hash, + &Transfers::from(transfers.to_owned()), + true, + ) .map_err(|err| BlockStoreError::InternalStorage(Box::new(err))) } @@ -281,7 +289,8 @@ impl LmdbBlockStore { txn: &mut RwTransaction, block_hash: &BlockHash, ) -> Result<(), BlockStoreError> { - txn.del(self.transfer_db, block_hash, None) + self.transfer_dbs + .delete(txn, block_hash) .map_err(|err| BlockStoreError::InternalStorage(Box::new(err))) } @@ -501,8 +510,9 @@ impl LmdbBlockStore { } } - let was_written = txn - .put_value(self.transfer_db, block_hash, &transfers, true) + let was_written = self + .transfer_dbs + .put(txn, block_hash, &Transfers::from(transfers), true) .map_err(|err| BlockStoreError::InternalStorage(Box::new(err)))?; if !was_written { error!(?block_hash, "failed to write transfers"); @@ -536,35 +546,40 @@ pub(crate) fn new_environment( /// Returns all `Transform::WriteTransfer`s from the execution effects if this is an /// `ExecutionResult::Success`, or an empty `Vec` if `ExecutionResult::Failure`. fn successful_transfers(execution_result: &ExecutionResult) -> Vec { - let mut transfers: Vec = vec![]; + let mut all_transfers: Vec = vec![]; match execution_result { ExecutionResult::V1(ExecutionResultV1::Success { effect, .. }) => { for transform_entry in &effect.transforms { - if let execution_result_v1::TransformKindV1::WriteTransfer(transfer) = + if let execution_result_v1::TransformKindV1::WriteTransfer(transfer_v1) = &transform_entry.transform { - transfers.push(*transfer); + all_transfers.push(Transfer::V1(transfer_v1.clone())); } } } - ExecutionResult::V2(ExecutionResultV2::Success { effects, .. }) => { - for transform in effects.transforms() { - if let TransformKindV2::Write(StoredValue::Transfer(transfer)) = transform.kind() { - transfers.push(*transfer); + ExecutionResult::V2(ExecutionResultV2 { + transfers, + error_message, + .. + }) => { + if error_message.is_none() { + for transfer in transfers { + all_transfers.push(transfer.clone()); } } + // else no-op: we only record transfers from successful executions. } - ExecutionResult::V1(ExecutionResultV1::Failure { .. }) - | ExecutionResult::V2(ExecutionResultV2::Failure { .. }) => { + ExecutionResult::V1(ExecutionResultV1::Failure { .. }) => { // No-op: we only record transfers from successful executions. } } - transfers + + all_transfers } impl BlockStoreProvider for LmdbBlockStore { - type Reader<'a> = LmdbBlockStoreTransaction<'a, RoTransaction<'a>>; - type ReaderWriter<'a> = LmdbBlockStoreTransaction<'a, RwTransaction<'a>>; + type Reader<'t> = LmdbBlockStoreTransaction<'t, RoTransaction<'t>>; + type ReaderWriter<'t> = LmdbBlockStoreTransaction<'t, RwTransaction<'t>>; fn checkout_ro(&self) -> Result, BlockStoreError> { let txn = self @@ -590,15 +605,15 @@ impl BlockStoreProvider for LmdbBlockStore { } } -pub struct LmdbBlockStoreTransaction<'a, T> +pub struct LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { txn: T, - block_store: &'a LmdbBlockStore, + block_store: &'t LmdbBlockStore, } -impl<'a, T> BlockStoreTransaction for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> BlockStoreTransaction for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -613,7 +628,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -626,7 +641,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -639,7 +654,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -652,7 +667,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -665,7 +680,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -681,7 +696,7 @@ where } } -impl<'a, T> DataReader> for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader> for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -700,7 +715,7 @@ where } } -impl<'a, T> DataReader for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -719,7 +734,7 @@ where } } -impl<'a, T> DataReader> for LmdbBlockStoreTransaction<'a, T> +impl<'t, T> DataReader> for LmdbBlockStoreTransaction<'t, T> where T: LmdbTransaction, { @@ -732,7 +747,7 @@ where } } -impl<'a, T, K> DataReader> for LmdbBlockStoreTransaction<'a, T> +impl<'t, T, K> DataReader> for LmdbBlockStoreTransaction<'t, T> where K: AsRef<[u8]>, T: LmdbTransaction, @@ -746,7 +761,7 @@ where } } -impl<'a> DataWriter for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> { +impl<'t> DataWriter for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { /// Writes a block to storage. fn write(&mut self, data: &Block) -> Result { self.block_store.write_block(&mut self.txn, data) @@ -764,8 +779,8 @@ impl<'a> DataWriter for LmdbBlockStoreTransaction<'a, RwTransa } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &ApprovalsHashes) -> Result { self.block_store.write_approvals_hashes(&mut self.txn, data) @@ -777,8 +792,8 @@ impl<'a> DataWriter } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &BlockSignatures) -> Result { self.block_store @@ -791,7 +806,7 @@ impl<'a> DataWriter } } -impl<'a> DataWriter for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> { +impl<'t> DataWriter for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &BlockHeader) -> Result { self.block_store.write_block_header(&mut self.txn, data) } @@ -801,8 +816,8 @@ impl<'a> DataWriter for LmdbBlockStoreTransaction<'a, Rw } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &Transaction) -> Result { self.block_store.write_transaction(&mut self.txn, data) @@ -813,8 +828,8 @@ impl<'a> DataWriter } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &BlockTransfers) -> Result { self.block_store @@ -827,8 +842,8 @@ impl<'a> DataWriter } } -impl<'a> DataWriter, StateStore> - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter, StateStore> + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write(&mut self, data: &StateStore) -> Result, BlockStoreError> { self.block_store @@ -841,8 +856,8 @@ impl<'a> DataWriter, StateStore> } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write( &mut self, @@ -868,8 +883,8 @@ impl<'a> DataWriter } } -impl<'a> DataWriter - for LmdbBlockStoreTransaction<'a, RwTransaction<'a>> +impl<'t> DataWriter + for LmdbBlockStoreTransaction<'t, RwTransaction<'t>> { fn write( &mut self, diff --git a/storage/src/block_store/lmdb/mod.rs b/storage/src/block_store/lmdb/mod.rs index c045886b2d..30ea9429fa 100644 --- a/storage/src/block_store/lmdb/mod.rs +++ b/storage/src/block_store/lmdb/mod.rs @@ -5,5 +5,110 @@ mod versioned_databases; mod indexed_lmdb_block_store; mod lmdb_block_store; +use core::convert::TryFrom; pub use indexed_lmdb_block_store::IndexedLmdbBlockStore; pub use lmdb_block_store::LmdbBlockStore; + +#[cfg(test)] +use rand::Rng; +use serde::Serialize; + +#[cfg(test)] +use casper_types::testing::TestRng; + +/// An identifier of db tables. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] +#[repr(u16)] +pub enum DbTableId { + /// Refers to `BlockHeader` db table. + BlockHeader = 0, + /// Refers to `BlockBody` db table. + BlockBody = 1, + /// Refers to `ApprovalsHashes` db table. + ApprovalsHashes = 2, + /// Refers to `BlockMetadata` db table. + BlockMetadata = 3, + /// Refers to `Transaction` db table. + Transaction = 4, + /// Refers to `ExecutionResult` db table. + ExecutionResult = 5, + /// Refers to `Transfer` db table. + Transfer = 6, + /// Refers to `FinalizedTransactionApprovals` db table. + FinalizedTransactionApprovals = 7, +} + +impl DbTableId { + #[cfg(test)] + pub fn random(rng: &mut TestRng) -> Self { + match rng.gen_range(0..8) { + 0 => DbTableId::BlockHeader, + 1 => DbTableId::BlockBody, + 2 => DbTableId::ApprovalsHashes, + 3 => DbTableId::BlockMetadata, + 4 => DbTableId::Transaction, + 5 => DbTableId::ExecutionResult, + 6 => DbTableId::Transfer, + 7 => DbTableId::FinalizedTransactionApprovals, + _ => unreachable!(), + } + } +} + +impl TryFrom for DbTableId { + type Error = UnknownDbTableId; + + fn try_from(value: u16) -> Result { + match value { + 0 => Ok(DbTableId::BlockHeader), + 1 => Ok(DbTableId::BlockBody), + 2 => Ok(DbTableId::ApprovalsHashes), + 3 => Ok(DbTableId::BlockMetadata), + 4 => Ok(DbTableId::Transaction), + 5 => Ok(DbTableId::ExecutionResult), + 6 => Ok(DbTableId::Transfer), + 7 => Ok(DbTableId::FinalizedTransactionApprovals), + _ => Err(UnknownDbTableId(value)), + } + } +} + +impl From for u16 { + fn from(value: DbTableId) -> Self { + value as u16 + } +} + +impl core::fmt::Display for DbTableId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + DbTableId::BlockHeader => write!(f, "BlockHeader"), + DbTableId::BlockBody => write!(f, "BlockBody"), + DbTableId::ApprovalsHashes => write!(f, "ApprovalsHashes"), + DbTableId::BlockMetadata => write!(f, "BlockMetadata"), + DbTableId::Transaction => write!(f, "Transaction"), + DbTableId::ExecutionResult => write!(f, "ExecutionResult"), + DbTableId::Transfer => write!(f, "Transfer"), + DbTableId::FinalizedTransactionApprovals => write!(f, "FinalizedTransactionApprovals"), + } + } +} + +/// Error returned when trying to convert a `u16` into a `DbTableId`. +#[derive(Debug, PartialEq, Eq)] +pub struct UnknownDbTableId(u16); + +#[cfg(test)] +mod tests { + use super::*; + use casper_types::testing::TestRng; + + #[test] + fn tag_roundtrip() { + let rng = &mut TestRng::new(); + + let val = DbTableId::random(rng); + let tag = u16::from(val); + assert_eq!(DbTableId::try_from(tag), Ok(val)); + } +} diff --git a/storage/src/block_store/lmdb/versioned_databases.rs b/storage/src/block_store/lmdb/versioned_databases.rs index f9da9f6127..b4d5fa2866 100644 --- a/storage/src/block_store/lmdb/versioned_databases.rs +++ b/storage/src/block_store/lmdb/versioned_databases.rs @@ -9,17 +9,19 @@ use serde::Serialize; use std::{collections::BTreeSet, marker::PhantomData}; use casper_types::{ - binary_port::DbRawBytesSpec, bytesrepr::{FromBytes, ToBytes}, execution::ExecutionResult, Approval, BlockBody, BlockBodyV1, BlockHash, BlockHeader, BlockHeaderV1, BlockSignatures, - BlockSignaturesV1, Deploy, DeployHash, Digest, Transaction, TransactionHash, + BlockSignaturesV1, Deploy, DeployHash, Digest, Transaction, TransactionHash, TransferV1, }; -use super::lmdb_ext::{self, LmdbExtError, TransactionExt, WriteTransactionExt}; -use crate::block_store::{ - error::BlockStoreError, - types::{ApprovalsHashes, DeployMetadataV1, LegacyApprovalsHashes}, +use super::{ + super::{ + error::BlockStoreError, + types::{ApprovalsHashes, DeployMetadataV1, LegacyApprovalsHashes, Transfers}, + DbRawBytesSpec, + }, + lmdb_ext::{self, LmdbExtError, TransactionExt, WriteTransactionExt}, }; pub(crate) trait VersionedKey: ToBytes { @@ -87,6 +89,10 @@ impl VersionedValue for BlockSignatures { type Legacy = BlockSignaturesV1; } +impl VersionedValue for Transfers { + type Legacy = Vec; +} + /// A pair of databases, one holding the original legacy form of the data, and the other holding the /// new versioned, future-proof form of the data. /// diff --git a/storage/src/block_store/mod.rs b/storage/src/block_store/mod.rs index 2b424d967c..657f924aff 100644 --- a/storage/src/block_store/mod.rs +++ b/storage/src/block_store/mod.rs @@ -5,3 +5,39 @@ pub mod types; pub use block_provider::{BlockStoreProvider, BlockStoreTransaction, DataReader, DataWriter}; pub use error::BlockStoreError; + +/// Stores raw bytes from the DB along with the flag indicating whether data come from legacy or +/// current version of the DB. +#[derive(Debug)] +pub struct DbRawBytesSpec { + is_legacy: bool, + raw_bytes: Vec, +} + +impl DbRawBytesSpec { + /// Creates a variant indicating that raw bytes are coming from the legacy database. + pub fn new_legacy(raw_bytes: &[u8]) -> Self { + Self { + is_legacy: true, + raw_bytes: raw_bytes.to_vec(), + } + } + + /// Creates a variant indicating that raw bytes are coming from the current database. + pub fn new_current(raw_bytes: &[u8]) -> Self { + Self { + is_legacy: false, + raw_bytes: raw_bytes.to_vec(), + } + } + + /// Is legacy? + pub fn is_legacy(&self) -> bool { + self.is_legacy + } + + /// Raw bytes. + pub fn into_raw_bytes(self) -> Vec { + self.raw_bytes + } +} diff --git a/storage/src/block_store/types/mod.rs b/storage/src/block_store/types/mod.rs index 74646be28a..ceb012c4cb 100644 --- a/storage/src/block_store/types/mod.rs +++ b/storage/src/block_store/types/mod.rs @@ -1,6 +1,7 @@ mod approvals_hashes; mod block_hash_height_and_era; mod deploy_metadata_v1; +mod transfers; use std::{ borrow::Cow, @@ -15,6 +16,7 @@ use casper_types::{ pub(crate) use approvals_hashes::LegacyApprovalsHashes; pub(crate) use deploy_metadata_v1::DeployMetadataV1; +pub(in crate::block_store) use transfers::Transfers; pub type ExecutionResults = HashMap; diff --git a/storage/src/block_store/types/transfers.rs b/storage/src/block_store/types/transfers.rs new file mode 100644 index 0000000000..159146fa68 --- /dev/null +++ b/storage/src/block_store/types/transfers.rs @@ -0,0 +1,52 @@ +use serde::{Deserialize, Serialize}; + +use casper_types::{ + bytesrepr::{self, FromBytes, ToBytes}, + Transfer, TransferV1, +}; + +/// A wrapped `Vec`, used as the value type in the `transfer_dbs`. +/// +/// It exists to allow the `impl From>` to be written, making the type suitable for +/// use as a parameter in a `VersionedDatabases`. +#[derive(Clone, Serialize, Deserialize, Debug, Default, PartialEq, Eq)] +pub(in crate::block_store) struct Transfers(Vec); + +impl Transfers { + pub(in crate::block_store) fn into_owned(self) -> Vec { + self.0 + } +} + +impl From> for Transfers { + fn from(v1_transfers: Vec) -> Self { + Transfers(v1_transfers.into_iter().map(Transfer::V1).collect()) + } +} + +impl From> for Transfers { + fn from(transfers: Vec) -> Self { + Transfers(transfers) + } +} + +impl ToBytes for Transfers { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + self.0.to_bytes() + } + + fn serialized_length(&self) -> usize { + self.0.serialized_length() + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.0.write_bytes(writer) + } +} + +impl FromBytes for Transfers { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + Vec::::from_bytes(bytes) + .map(|(transfers, remainder)| (Transfers(transfers), remainder)) + } +} diff --git a/storage/src/data_access_layer.rs b/storage/src/data_access_layer.rs index db824919e6..c264576d98 100644 --- a/storage/src/data_access_layer.rs +++ b/storage/src/data_access_layer.rs @@ -7,8 +7,9 @@ use casper_types::{execution::Effects, Digest, EraId}; use crate::tracking_copy::TrackingCopy; mod addressable_entity; +pub mod auction; pub mod balance; -pub mod bidding; +mod balance_hold; pub mod bids; pub mod block_rewards; pub mod era_validators; @@ -16,6 +17,8 @@ mod execution_results_checksum; mod fee; mod flush; mod genesis; +pub mod handle_payment; +pub mod mint; mod protocol_upgrade; pub mod prune; pub mod query; @@ -24,12 +27,14 @@ pub mod step; mod system_entity_registry; pub mod tagged_values; mod total_supply; -pub mod transfer; mod trie; pub use addressable_entity::{AddressableEntityRequest, AddressableEntityResult}; +pub use auction::{AuctionMethod, BiddingRequest, BiddingResult}; pub use balance::{BalanceIdentifier, BalanceRequest, BalanceResult}; -pub use bidding::{BiddingRequest, BiddingResult}; +pub use balance_hold::{ + BalanceHoldError, BalanceHoldRequest, BalanceHoldResult, InsufficientBalanceHandling, +}; pub use bids::{BidsRequest, BidsResult}; pub use block_rewards::{BlockRewardsError, BlockRewardsRequest, BlockRewardsResult}; pub use era_validators::{EraValidatorsRequest, EraValidatorsResult}; @@ -40,6 +45,8 @@ pub use execution_results_checksum::{ pub use fee::{FeeError, FeeRequest, FeeResult}; pub use flush::{FlushRequest, FlushResult}; pub use genesis::{GenesisRequest, GenesisResult}; +pub use handle_payment::{HandlePaymentMode, HandlePaymentRequest, HandlePaymentResult}; +pub use mint::{TransferRequest, TransferResult}; pub use protocol_upgrade::{ProtocolUpgradeRequest, ProtocolUpgradeResult}; pub use prune::{PruneRequest, PruneResult}; pub use query::{QueryRequest, QueryResult}; @@ -50,11 +57,8 @@ pub use system_entity_registry::{ SystemEntityRegistrySelector, }; pub use total_supply::{TotalSupplyRequest, TotalSupplyResult}; -pub use transfer::{TransferRequest, TransferResult}; pub use trie::{PutTrieRequest, PutTrieResult, TrieElement, TrieRequest, TrieResult}; -pub use bidding::AuctionMethod; - pub struct Block { _era_id: EraId, } diff --git a/storage/src/data_access_layer/auction.rs b/storage/src/data_access_layer/auction.rs new file mode 100644 index 0000000000..3970b3429a --- /dev/null +++ b/storage/src/data_access_layer/auction.rs @@ -0,0 +1,298 @@ +use std::collections::BTreeSet; + +use serde::Serialize; +use thiserror::Error; +use tracing::error; + +use casper_types::{ + account::AccountHash, + bytesrepr::FromBytes, + execution::Effects, + system::{auction, auction::DelegationRate}, + CLTyped, CLValue, CLValueError, Chainspec, Digest, HoldsEpoch, InitiatorAddr, ProtocolVersion, + PublicKey, RuntimeArgs, TransactionEntryPoint, TransactionHash, U512, +}; + +use crate::{ + system::runtime_native::Config as NativeRuntimeConfig, tracking_copy::TrackingCopyError, +}; + +/// An error returned when constructing an [`AuctionMethod`]. +#[derive(Clone, Eq, PartialEq, Error, Serialize, Debug)] +pub enum AuctionMethodError { + /// Provided entry point is not one of the Auction ones. + #[error("invalid entry point for auction: {0}")] + InvalidEntryPoint(TransactionEntryPoint), + /// Required arg missing. + #[error("missing '{0}' arg")] + MissingArg(String), + /// Failed to parse the given arg. + #[error("failed to parse '{arg}' arg: {error}")] + CLValue { + /// The arg name. + arg: String, + /// The failure. + error: CLValueError, + }, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AuctionMethod { + ActivateBid { + validator: PublicKey, + }, + AddBid { + public_key: PublicKey, + delegation_rate: DelegationRate, + amount: U512, + holds_epoch: HoldsEpoch, + }, + WithdrawBid { + public_key: PublicKey, + amount: U512, + }, + Delegate { + delegator: PublicKey, + validator: PublicKey, + amount: U512, + max_delegators_per_validator: u32, + minimum_delegation_amount: u64, + holds_epoch: HoldsEpoch, + }, + Undelegate { + delegator: PublicKey, + validator: PublicKey, + amount: U512, + }, + Redelegate { + delegator: PublicKey, + validator: PublicKey, + amount: U512, + new_validator: PublicKey, + minimum_delegation_amount: u64, + }, +} + +impl AuctionMethod { + pub fn from_parts( + entry_point: TransactionEntryPoint, + runtime_args: &RuntimeArgs, + holds_epoch: HoldsEpoch, + chainspec: &Chainspec, + ) -> Result { + match entry_point { + TransactionEntryPoint::Custom(_) | TransactionEntryPoint::Transfer => { + Err(AuctionMethodError::InvalidEntryPoint(entry_point)) + } + TransactionEntryPoint::ActivateBid => Self::new_activate_bid(runtime_args), + TransactionEntryPoint::AddBid => Self::new_add_bid(runtime_args, holds_epoch), + TransactionEntryPoint::WithdrawBid => Self::new_withdraw_bid(runtime_args), + TransactionEntryPoint::Delegate => Self::new_delegate( + runtime_args, + chainspec.core_config.max_delegators_per_validator, + chainspec.core_config.minimum_delegation_amount, + holds_epoch, + ), + TransactionEntryPoint::Undelegate => Self::new_undelegate(runtime_args), + TransactionEntryPoint::Redelegate => Self::new_redelegate( + runtime_args, + chainspec.core_config.minimum_delegation_amount, + ), + } + } + + fn new_activate_bid(runtime_args: &RuntimeArgs) -> Result { + let validator = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; + Ok(Self::ActivateBid { validator }) + } + + fn new_add_bid( + runtime_args: &RuntimeArgs, + holds_epoch: HoldsEpoch, + ) -> Result { + let public_key = Self::get_named_argument(runtime_args, auction::ARG_PUBLIC_KEY)?; + let delegation_rate = Self::get_named_argument(runtime_args, auction::ARG_DELEGATION_RATE)?; + let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + Ok(Self::AddBid { + public_key, + delegation_rate, + amount, + holds_epoch, + }) + } + + fn new_withdraw_bid(runtime_args: &RuntimeArgs) -> Result { + let public_key = Self::get_named_argument(runtime_args, auction::ARG_PUBLIC_KEY)?; + let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + Ok(Self::WithdrawBid { public_key, amount }) + } + + fn new_delegate( + runtime_args: &RuntimeArgs, + max_delegators_per_validator: u32, + minimum_delegation_amount: u64, + holds_epoch: HoldsEpoch, + ) -> Result { + let delegator = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; + let validator = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; + let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + + Ok(Self::Delegate { + delegator, + validator, + amount, + max_delegators_per_validator, + minimum_delegation_amount, + holds_epoch, + }) + } + + fn new_undelegate(runtime_args: &RuntimeArgs) -> Result { + let delegator = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; + let validator = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; + let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + + Ok(Self::Undelegate { + delegator, + validator, + amount, + }) + } + + fn new_redelegate( + runtime_args: &RuntimeArgs, + minimum_delegation_amount: u64, + ) -> Result { + let delegator = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; + let validator = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; + let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; + let new_validator = Self::get_named_argument(runtime_args, auction::ARG_NEW_VALIDATOR)?; + + Ok(Self::Redelegate { + delegator, + validator, + amount, + new_validator, + minimum_delegation_amount, + }) + } + + fn get_named_argument( + args: &RuntimeArgs, + name: &str, + ) -> Result { + let arg: &CLValue = args + .get(name) + .ok_or_else(|| AuctionMethodError::MissingArg(name.to_string()))?; + arg.to_t().map_err(|error| AuctionMethodError::CLValue { + arg: name.to_string(), + error, + }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BiddingRequest { + /// The runtime config. + pub(crate) config: NativeRuntimeConfig, + /// State root hash. + pub(crate) state_hash: Digest, + /// The protocol version. + pub(crate) protocol_version: ProtocolVersion, + /// The auction method. + pub(crate) auction_method: AuctionMethod, + /// Transaction hash. + pub(crate) transaction_hash: TransactionHash, + /// Base account. + pub(crate) initiator: InitiatorAddr, + /// List of authorizing accounts. + pub(crate) authorization_keys: BTreeSet, +} + +impl BiddingRequest { + /// Creates new request instance with runtime args. + #[allow(clippy::too_many_arguments)] + pub fn new( + config: NativeRuntimeConfig, + state_hash: Digest, + protocol_version: ProtocolVersion, + transaction_hash: TransactionHash, + initiator: InitiatorAddr, + authorization_keys: BTreeSet, + auction_method: AuctionMethod, + ) -> Self { + Self { + config, + state_hash, + protocol_version, + transaction_hash, + initiator, + authorization_keys, + auction_method, + } + } + + pub fn config(&self) -> &NativeRuntimeConfig { + &self.config + } + + pub fn state_hash(&self) -> Digest { + self.state_hash + } + + pub fn protocol_version(&self) -> ProtocolVersion { + self.protocol_version + } + + pub fn auction_method(&self) -> &AuctionMethod { + &self.auction_method + } + + pub fn transaction_hash(&self) -> TransactionHash { + self.transaction_hash + } + + pub fn initiator(&self) -> &InitiatorAddr { + &self.initiator + } + + pub fn authorization_keys(&self) -> &BTreeSet { + &self.authorization_keys + } +} + +#[derive(Debug, Clone)] +pub enum AuctionMethodRet { + Unit, + UpdatedAmount(U512), +} + +#[derive(Debug)] +pub enum BiddingResult { + /// Invalid state root hash. + RootNotFound, + /// Bidding request succeeded + Success { + // The ret value, if any. + ret: AuctionMethodRet, + /// Effects of bidding interaction. + effects: Effects, + }, + /// Bidding request failed. + Failure(TrackingCopyError), +} + +impl BiddingResult { + /// Is this a success. + pub fn is_success(&self) -> bool { + matches!(self, BiddingResult::Success { .. }) + } + + /// Effects. + pub fn effects(&self) -> Effects { + match self { + BiddingResult::RootNotFound | BiddingResult::Failure(_) => Effects::new(), + BiddingResult::Success { effects, .. } => effects.clone(), + } + } +} diff --git a/storage/src/data_access_layer/balance.rs b/storage/src/data_access_layer/balance.rs index 54065b01db..14510c7c32 100644 --- a/storage/src/data_access_layer/balance.rs +++ b/storage/src/data_access_layer/balance.rs @@ -1,29 +1,154 @@ //! Types for balance queries. +use crate::data_access_layer::BalanceHoldRequest; use casper_types::{ - account::AccountHash, global_state::TrieMerkleProof, Digest, EntityAddr, Key, ProtocolVersion, + account::AccountHash, + global_state::TrieMerkleProof, + system::{ + handle_payment::{ACCUMULATION_PURSE_KEY, PAYMENT_PURSE_KEY}, + mint::BalanceHoldAddrTag, + HANDLE_PAYMENT, + }, + AccessRights, BlockTime, Digest, EntityAddr, HoldsEpoch, InitiatorAddr, Key, ProtocolVersion, PublicKey, StoredValue, URef, URefAddr, U512, }; +use std::collections::BTreeMap; +use tracing::error; -use crate::tracking_copy::TrackingCopyError; +use crate::{ + global_state::state::StateReader, + tracking_copy::{TrackingCopyEntityExt, TrackingCopyError, TrackingCopyExt}, + TrackingCopy, +}; + +/// How to handle available balance inquiry? +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub enum BalanceHandling { + /// Ignore balance holds. + #[default] + Total, + /// Adjust for balance holds (if any). + Available { holds_epoch: HoldsEpoch }, +} /// Represents a way to make a balance inquiry. #[derive(Debug, Clone, PartialEq, Eq)] pub enum BalanceIdentifier { + Payment, + Accumulate, Purse(URef), Public(PublicKey), Account(AccountHash), Entity(EntityAddr), Internal(URefAddr), + PenalizedAccount(AccountHash), } impl BalanceIdentifier { - pub fn as_key(&self) -> Key { + pub fn as_purse_addr(&self) -> Option { match self { - BalanceIdentifier::Purse(uref) => Key::URef(*uref), - BalanceIdentifier::Public(public_key) => Key::Account(public_key.to_account_hash()), - BalanceIdentifier::Account(account_hash) => Key::Account(*account_hash), - BalanceIdentifier::Entity(entity_addr) => Key::AddressableEntity(*entity_addr), - BalanceIdentifier::Internal(addr) => Key::Balance(*addr), + BalanceIdentifier::Internal(addr) => Some(*addr), + BalanceIdentifier::Purse(uref) => Some(uref.addr()), + BalanceIdentifier::Public(_) + | BalanceIdentifier::Account(_) + | BalanceIdentifier::PenalizedAccount(_) + | BalanceIdentifier::Entity(_) + | BalanceIdentifier::Payment + | BalanceIdentifier::Accumulate => None, + } + } + + /// Return purse_uref, if able. + pub fn purse_uref( + &self, + tc: &mut TrackingCopy, + protocol_version: ProtocolVersion, + ) -> Result + where + S: StateReader, + { + let purse_uref = match self { + BalanceIdentifier::Internal(addr) => URef::new(*addr, AccessRights::READ), + BalanceIdentifier::Purse(purse_uref) => *purse_uref, + BalanceIdentifier::Public(public_key) => { + let account_hash = public_key.to_account_hash(); + match tc.get_addressable_entity_by_account_hash(protocol_version, account_hash) { + Ok(entity) => entity.main_purse(), + Err(tce) => return Err(tce), + } + } + BalanceIdentifier::Account(account_hash) + | BalanceIdentifier::PenalizedAccount(account_hash) => { + match tc.get_addressable_entity_by_account_hash(protocol_version, *account_hash) { + Ok(entity) => entity.main_purse(), + Err(tce) => return Err(tce), + } + } + BalanceIdentifier::Entity(entity_addr) => { + match tc.get_addressable_entity(*entity_addr) { + Ok(entity) => entity.main_purse(), + Err(tce) => return Err(tce), + } + } + BalanceIdentifier::Payment => { + self.get_system_purse(tc, HANDLE_PAYMENT, PAYMENT_PURSE_KEY)? + } + BalanceIdentifier::Accumulate => { + self.get_system_purse(tc, HANDLE_PAYMENT, ACCUMULATION_PURSE_KEY)? + } + }; + Ok(purse_uref) + } + + fn get_system_purse( + &self, + tc: &mut TrackingCopy, + system_contract_name: &str, + named_key_name: &str, + ) -> Result + where + S: StateReader, + { + let system_contract_registry = tc.get_system_entity_registry()?; + + let entity_hash = system_contract_registry + .get(system_contract_name) + .ok_or_else(|| { + error!("Missing system handle payment contract hash"); + TrackingCopyError::MissingSystemContractHash(system_contract_name.to_string()) + })?; + + let named_keys = tc.get_named_keys(EntityAddr::System(entity_hash.value()))?; + let named_key = + named_keys + .get(named_key_name) + .ok_or(TrackingCopyError::NamedKeyNotFound( + named_key_name.to_string(), + ))?; + let uref = named_key + .as_uref() + .ok_or(TrackingCopyError::UnexpectedKeyVariant(*named_key))?; + Ok(*uref) + } + + /// Is this balance identifier for penalty? + pub fn is_penalty(&self) -> bool { + // currently there is one variant of this kind, but more may be added later to + // support more use cases. + matches!(self, BalanceIdentifier::PenalizedAccount(_)) + } +} + +impl Default for BalanceIdentifier { + fn default() -> Self { + BalanceIdentifier::Purse(URef::default()) + } +} + +impl From for BalanceIdentifier { + fn from(value: InitiatorAddr) -> Self { + match value { + InitiatorAddr::PublicKey(public_key) => BalanceIdentifier::Public(public_key), + InitiatorAddr::AccountHash(account_hash) => BalanceIdentifier::Account(account_hash), } } } @@ -34,6 +159,7 @@ pub struct BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, identifier: BalanceIdentifier, + balance_handling: BalanceHandling, } impl BalanceRequest { @@ -42,11 +168,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, identifier: BalanceIdentifier, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier, + balance_handling, } } @@ -55,11 +183,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, purse_uref: URef, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier: BalanceIdentifier::Purse(purse_uref), + balance_handling, } } @@ -68,11 +198,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, public_key: PublicKey, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier: BalanceIdentifier::Public(public_key), + balance_handling, } } @@ -81,11 +213,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, account_hash: AccountHash, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier: BalanceIdentifier::Account(account_hash), + balance_handling, } } @@ -94,11 +228,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, entity_addr: EntityAddr, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier: BalanceIdentifier::Entity(entity_addr), + balance_handling, } } @@ -107,11 +243,13 @@ impl BalanceRequest { state_hash: Digest, protocol_version: ProtocolVersion, balance_addr: URefAddr, + balance_handling: BalanceHandling, ) -> Self { BalanceRequest { state_hash, protocol_version, identifier: BalanceIdentifier::Internal(balance_addr), + balance_handling, } } @@ -129,8 +267,31 @@ impl BalanceRequest { pub fn identifier(&self) -> &BalanceIdentifier { &self.identifier } + + /// Returns the block time. + pub fn balance_handling(&self) -> BalanceHandling { + self.balance_handling + } } +impl From for BalanceRequest { + fn from(request: BalanceHoldRequest) -> Self { + let balance_handling = BalanceHandling::Available { + holds_epoch: request.holds_epoch(), + }; + BalanceRequest::new( + request.state_hash(), + request.protocol_version(), + request.identifier().clone(), + balance_handling, + ) + } +} + +/// Balance holds with Merkle proofs. +pub type BalanceHoldsWithProof = + BTreeMap)>; + /// Result enum that represents all possible outcomes of a balance request. #[derive(Debug)] pub enum BalanceResult { @@ -138,10 +299,16 @@ pub enum BalanceResult { RootNotFound, /// A query returned a balance. Success { - /// Purse balance. - motes: U512, + /// The purse address. + purse_addr: URefAddr, + /// The purses total balance, not considering holds. + total_balance: U512, + /// The available balance (total balance - sum of all active holds). + available_balance: U512, /// A proof that the given value is present in the Merkle trie. - proof: Box>, + total_balance_proof: Box>, + /// Any time-relevant active holds on the balance. + balance_holds: BTreeMap, }, Failure(TrackingCopyError), } @@ -150,7 +317,10 @@ impl BalanceResult { /// Returns the amount of motes for a [`BalanceResult::Success`] variant. pub fn motes(&self) -> Option<&U512> { match self { - BalanceResult::Success { motes, .. } => Some(motes), + BalanceResult::Success { + available_balance: motes, + .. + } => Some(motes), _ => None, } } @@ -158,8 +328,29 @@ impl BalanceResult { /// Returns the Merkle proof for a given [`BalanceResult::Success`] variant. pub fn proof(self) -> Option> { match self { - BalanceResult::Success { proof, .. } => Some(*proof), + BalanceResult::Success { + total_balance_proof: proof, + .. + } => Some(*proof), _ => None, } } + + /// Is the available balance sufficient to cover the cost? + pub fn is_sufficient(&self, cost: U512) -> bool { + match self { + BalanceResult::RootNotFound | BalanceResult::Failure(_) => false, + BalanceResult::Success { + available_balance, .. + } => available_balance >= &cost, + } + } + + /// Was the balance request successful? + pub fn is_success(&self) -> bool { + match self { + BalanceResult::RootNotFound | BalanceResult::Failure(_) => false, + BalanceResult::Success { .. } => true, + } + } } diff --git a/storage/src/data_access_layer/balance_hold.rs b/storage/src/data_access_layer/balance_hold.rs new file mode 100644 index 0000000000..38e472e188 --- /dev/null +++ b/storage/src/data_access_layer/balance_hold.rs @@ -0,0 +1,321 @@ +use crate::{data_access_layer::BalanceIdentifier, tracking_copy::TrackingCopyError}; +use casper_types::{ + account::AccountHash, execution::Effects, system::mint::BalanceHoldAddrTag, BlockTime, Digest, + EntityAddr, HoldsEpoch, ProtocolVersion, PublicKey, URef, URefAddr, U512, +}; +use std::fmt::{Display, Formatter}; +use thiserror::Error; + +/// How to handle available balance is less than hold amount? +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub enum InsufficientBalanceHandling { + /// Hold however much balance remains. + #[default] + HoldRemaining, + /// No operation. Aka, do not place a hold. + Noop, +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct BalanceHoldRequest { + state_hash: Digest, + protocol_version: ProtocolVersion, + identifier: BalanceIdentifier, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, +} + +impl BalanceHoldRequest { + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn new( + state_hash: Digest, + protocol_version: ProtocolVersion, + identifier: BalanceIdentifier, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier, + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn from_purse( + state_hash: Digest, + protocol_version: ProtocolVersion, + purse_uref: URef, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier: BalanceIdentifier::Purse(purse_uref), + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn from_public_key( + state_hash: Digest, + protocol_version: ProtocolVersion, + public_key: PublicKey, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier: BalanceIdentifier::Public(public_key), + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn from_account_hash( + state_hash: Digest, + protocol_version: ProtocolVersion, + account_hash: AccountHash, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier: BalanceIdentifier::Account(account_hash), + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn from_entity_addr( + state_hash: Digest, + protocol_version: ProtocolVersion, + entity_addr: EntityAddr, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier: BalanceIdentifier::Entity(entity_addr), + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Creates a new [`BalanceHoldRequest`]. + #[allow(clippy::too_many_arguments)] + pub fn from_internal( + state_hash: Digest, + protocol_version: ProtocolVersion, + balance_addr: URefAddr, + hold_kind: BalanceHoldAddrTag, + hold_amount: U512, + block_time: BlockTime, + holds_epoch: HoldsEpoch, + insufficient_handling: InsufficientBalanceHandling, + ) -> Self { + BalanceHoldRequest { + state_hash, + protocol_version, + identifier: BalanceIdentifier::Internal(balance_addr), + hold_kind, + hold_amount, + block_time, + holds_epoch, + insufficient_handling, + } + } + + /// Returns a state hash. + pub fn state_hash(&self) -> Digest { + self.state_hash + } + + /// Protocol version. + pub fn protocol_version(&self) -> ProtocolVersion { + self.protocol_version + } + + /// Returns the identifier [`BalanceIdentifier`]. + pub fn identifier(&self) -> &BalanceIdentifier { + &self.identifier + } + + /// Returns the hold kind. + pub fn hold_kind(&self) -> BalanceHoldAddrTag { + self.hold_kind + } + + /// Returns the hold amount. + pub fn hold_amount(&self) -> U512 { + self.hold_amount + } + + /// Returns the block time. + pub fn block_time(&self) -> BlockTime { + self.block_time + } + + /// Returns the holds epoch. + pub fn holds_epoch(&self) -> HoldsEpoch { + self.holds_epoch + } + + /// Returns insufficient balance handling option. + pub fn insufficient_handling(&self) -> InsufficientBalanceHandling { + self.insufficient_handling + } +} + +/// Possible balance hold errors. +#[derive(Error, Debug, Clone)] +#[non_exhaustive] +pub enum BalanceHoldError { + TrackingCopy(TrackingCopyError), + InsufficientBalance { remaining_balance: U512 }, +} + +impl Display for BalanceHoldError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + BalanceHoldError::TrackingCopy(err) => { + write!(f, "TrackingCopy: {}", err) + } + BalanceHoldError::InsufficientBalance { remaining_balance } => { + write!(f, "InsufficientBalance: {}", remaining_balance) + } + } + } +} + +/// Result enum that represents all possible outcomes of a balance hold request. +#[derive(Debug)] +pub enum BalanceHoldResult { + /// Returned if a passed state root hash is not found. + RootNotFound, + /// Balance hold successfully placed. + Success { + /// Purse total balance. + total_balance: Box, + /// Purse available balance after hold placed. + available_balance: Box, + /// How much were we supposed to hold? + hold: Box, + /// How much did we actually hold? + held: Box, + /// Effects of bidding interaction. + effects: Box, + }, + /// Failed to place balance hold. + Failure(BalanceHoldError), +} + +impl BalanceHoldResult { + pub fn success( + total_balance: U512, + available_balance: U512, + hold: U512, + held: U512, + effects: Effects, + ) -> Self { + BalanceHoldResult::Success { + total_balance: Box::new(total_balance), + available_balance: Box::new(available_balance), + hold: Box::new(hold), + held: Box::new(held), + effects: Box::new(effects), + } + } + + /// Was the hold fully covered? + pub fn is_fully_covered(&self) -> bool { + match self { + BalanceHoldResult::RootNotFound | BalanceHoldResult::Failure(_) => false, + BalanceHoldResult::Success { hold, held, .. } => hold == held, + } + } + + /// Was the hold successful? + pub fn is_success(&self) -> bool { + matches!(self, BalanceHoldResult::Success { .. }) + } + + /// Was the root not found? + pub fn is_root_not_found(&self) -> bool { + matches!(self, BalanceHoldResult::RootNotFound) + } + + /// The effects, if any. + pub fn effects(&self) -> Effects { + match self { + BalanceHoldResult::RootNotFound | BalanceHoldResult::Failure(_) => Effects::new(), + BalanceHoldResult::Success { effects, .. } => *effects.clone(), + } + } + + pub fn error_message(&self) -> String { + match self { + BalanceHoldResult::Success { hold, held, .. } => { + if hold == held { + String::default() + } else { + format!( + "insufficient balance to cover hold amount: {}, held remaining amount: {}", + hold, held + ) + } + } + BalanceHoldResult::RootNotFound => "root not found".to_string(), + BalanceHoldResult::Failure(bhe) => { + format!("{:?}", bhe) + } + } + } +} diff --git a/storage/src/data_access_layer/bidding.rs b/storage/src/data_access_layer/bidding.rs deleted file mode 100644 index e46dcae41f..0000000000 --- a/storage/src/data_access_layer/bidding.rs +++ /dev/null @@ -1,278 +0,0 @@ -use crate::{ - system::runtime_native::Config as NativeRuntimeConfig, tracking_copy::TrackingCopyError, -}; -use casper_types::{ - account::AccountHash, - bytesrepr::FromBytes, - execution::Effects, - system::{auction, auction::DelegationRate}, - CLTyped, CLValue, Chainspec, Digest, ProtocolVersion, PublicKey, RuntimeArgs, - TransactionEntryPoint, TransactionHash, U512, -}; -use std::collections::BTreeSet; -use tracing::error; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum AuctionMethod { - ActivateBid { - validator_public_key: PublicKey, - }, - AddBid { - public_key: PublicKey, - delegation_rate: DelegationRate, - amount: U512, - }, - WithdrawBid { - public_key: PublicKey, - amount: U512, - }, - Delegate { - delegator_public_key: PublicKey, - validator_public_key: PublicKey, - amount: U512, - max_delegators_per_validator: u32, - minimum_delegation_amount: u64, - }, - Undelegate { - delegator_public_key: PublicKey, - validator_public_key: PublicKey, - amount: U512, - }, - Redelegate { - delegator_public_key: PublicKey, - validator_public_key: PublicKey, - amount: U512, - new_validator: PublicKey, - minimum_delegation_amount: u64, - }, -} - -#[allow(clippy::result_unit_err)] -impl AuctionMethod { - pub fn from_parts( - entry_point: TransactionEntryPoint, - runtime_args: &RuntimeArgs, - chainspec: &Chainspec, - ) -> Result { - match entry_point { - TransactionEntryPoint::Custom(_) | TransactionEntryPoint::Transfer => { - error!( - "attempt to get auction method using a non-auction entry point {}", - entry_point - ); - Err(()) - } - TransactionEntryPoint::ActivateBid => { - Self::activate_bid_from_args(runtime_args, chainspec) - } - TransactionEntryPoint::AddBid => Self::add_bid_from_args(runtime_args, chainspec), - TransactionEntryPoint::WithdrawBid => { - Self::withdraw_bid_from_args(runtime_args, chainspec) - } - TransactionEntryPoint::Delegate => Self::delegate_from_args(runtime_args, chainspec), - TransactionEntryPoint::Undelegate => { - Self::undelegate_from_args(runtime_args, chainspec) - } - TransactionEntryPoint::Redelegate => { - Self::redelegate_from_args(runtime_args, chainspec) - } - } - } - - pub fn activate_bid_from_args( - runtime_args: &RuntimeArgs, - _chainspec: &Chainspec, - ) -> Result { - let validator_public_key: PublicKey = - Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR_PUBLIC_KEY)?; - Ok(Self::ActivateBid { - validator_public_key, - }) - } - - pub fn add_bid_from_args( - runtime_args: &RuntimeArgs, - _chainspec: &Chainspec, - ) -> Result { - let public_key = Self::get_named_argument(runtime_args, auction::ARG_PUBLIC_KEY)?; - let delegation_rate = Self::get_named_argument(runtime_args, auction::ARG_DELEGATION_RATE)?; - let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; - Ok(Self::AddBid { - public_key, - delegation_rate, - amount, - }) - } - - pub fn withdraw_bid_from_args( - runtime_args: &RuntimeArgs, - _chainspec: &Chainspec, - ) -> Result { - let public_key = Self::get_named_argument(runtime_args, auction::ARG_PUBLIC_KEY)?; - let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; - Ok(Self::WithdrawBid { public_key, amount }) - } - - pub fn delegate_from_args( - runtime_args: &RuntimeArgs, - chainspec: &Chainspec, - ) -> Result { - let delegator_public_key = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; - let validator_public_key = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; - let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; - - let max_delegators_per_validator = chainspec.core_config.max_delegators_per_validator; - let minimum_delegation_amount = chainspec.core_config.minimum_delegation_amount; - - Ok(Self::Delegate { - delegator_public_key, - validator_public_key, - amount, - max_delegators_per_validator, - minimum_delegation_amount, - }) - } - - pub fn undelegate_from_args( - runtime_args: &RuntimeArgs, - _chainspec: &Chainspec, - ) -> Result { - let delegator_public_key = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; - let validator_public_key = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; - let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; - - Ok(Self::Undelegate { - delegator_public_key, - validator_public_key, - amount, - }) - } - - pub fn redelegate_from_args( - runtime_args: &RuntimeArgs, - chainspec: &Chainspec, - ) -> Result { - let delegator_public_key = Self::get_named_argument(runtime_args, auction::ARG_DELEGATOR)?; - let validator_public_key = Self::get_named_argument(runtime_args, auction::ARG_VALIDATOR)?; - let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?; - let new_validator = Self::get_named_argument(runtime_args, auction::ARG_NEW_VALIDATOR)?; - - let minimum_delegation_amount = chainspec.core_config.minimum_delegation_amount; - - Ok(Self::Redelegate { - delegator_public_key, - validator_public_key, - amount, - new_validator, - minimum_delegation_amount, - }) - } - - fn get_named_argument(args: &RuntimeArgs, name: &str) -> Result { - let arg: CLValue = args.get(name).cloned().ok_or(())?; - match arg.into_t() { - Ok(val) => Ok(val), - Err(err) => { - error!("{:?}", err); - Err(()) - } - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct BiddingRequest { - /// The runtime config. - config: NativeRuntimeConfig, - /// State root hash. - state_hash: Digest, - /// Block time represented as a unix timestamp. - block_time: u64, - /// The protocol version. - protocol_version: ProtocolVersion, - /// The auction method. - auction_method: AuctionMethod, - /// Transaction hash. - transaction_hash: TransactionHash, - /// Base account. - address: AccountHash, - /// List of authorizing accounts. - authorization_keys: BTreeSet, -} - -impl BiddingRequest { - /// Creates new request instance with runtime args. - #[allow(clippy::too_many_arguments)] - pub fn new( - config: NativeRuntimeConfig, - state_hash: Digest, - block_time: u64, - protocol_version: ProtocolVersion, - transaction_hash: TransactionHash, - address: AccountHash, - authorization_keys: BTreeSet, - auction_method: AuctionMethod, - ) -> Self { - Self { - config, - state_hash, - block_time, - protocol_version, - transaction_hash, - address, - authorization_keys, - auction_method, - } - } - - pub fn config(&self) -> &NativeRuntimeConfig { - &self.config - } - - pub fn state_hash(&self) -> Digest { - self.state_hash - } - - pub fn protocol_version(&self) -> ProtocolVersion { - self.protocol_version - } - - pub fn auction_method(&self) -> AuctionMethod { - self.auction_method.clone() - } - - pub fn transaction_hash(&self) -> TransactionHash { - self.transaction_hash - } - - pub fn address(&self) -> AccountHash { - self.address - } - - pub fn authorization_keys(&self) -> &BTreeSet { - &self.authorization_keys - } -} - -#[derive(Debug, Clone)] -pub enum AuctionMethodRet { - Unit, - UpdatedAmount(U512), -} - -#[derive(Debug)] -pub enum BiddingResult { - /// Invalid state root hash. - RootNotFound, - /// Transfer succeeded - Success { - // The ret value, if any. - ret: AuctionMethodRet, - /// State hash after bidding interaction is committed to the global state. - post_state_hash: Digest, - /// Effects of bidding interaction. - effects: Effects, - }, - /// Bidding request failed - Failure(TrackingCopyError), -} diff --git a/storage/src/data_access_layer/block_rewards.rs b/storage/src/data_access_layer/block_rewards.rs index d4bc69f1db..3d3da50757 100644 --- a/storage/src/data_access_layer/block_rewards.rs +++ b/storage/src/data_access_layer/block_rewards.rs @@ -1,10 +1,12 @@ -use casper_types::{ - execution::Effects, system::auction::Error as AuctionError, Digest, ProtocolVersion, PublicKey, - U512, -}; use std::collections::BTreeMap; + use thiserror::Error; +use casper_types::{ + execution::Effects, system::auction::Error as AuctionError, BlockTime, Digest, ProtocolVersion, + PublicKey, U512, +}; + use crate::{ system::{runtime_native::Config, transfer::TransferError}, tracking_copy::TrackingCopyError, @@ -16,7 +18,7 @@ pub struct BlockRewardsRequest { state_hash: Digest, protocol_version: ProtocolVersion, rewards: BTreeMap, - block_time: u64, + block_time: BlockTime, } impl BlockRewardsRequest { @@ -24,7 +26,7 @@ impl BlockRewardsRequest { config: Config, state_hash: Digest, protocol_version: ProtocolVersion, - block_time: u64, + block_time: BlockTime, rewards: BTreeMap, ) -> Self { BlockRewardsRequest { @@ -57,7 +59,7 @@ impl BlockRewardsRequest { } /// Returns block time. - pub fn block_time(&self) -> u64 { + pub fn block_time(&self) -> BlockTime { self.block_time } } diff --git a/storage/src/data_access_layer/fee.rs b/storage/src/data_access_layer/fee.rs index 6d7a158357..38fd942a27 100644 --- a/storage/src/data_access_layer/fee.rs +++ b/storage/src/data_access_layer/fee.rs @@ -6,7 +6,8 @@ use crate::system::{ transfer::TransferError, }; use casper_types::{ - account::AccountHash, execution::Effects, Digest, FeeHandling, ProtocolVersion, TransferAddr, + account::AccountHash, execution::Effects, BlockTime, Digest, FeeHandling, HoldsEpoch, + ProtocolVersion, Transfer, }; use crate::tracking_copy::TrackingCopyError; @@ -16,7 +17,8 @@ pub struct FeeRequest { config: NativeRuntimeConfig, state_hash: Digest, protocol_version: ProtocolVersion, - block_time: u64, + block_time: BlockTime, + holds_epoch: HoldsEpoch, } impl FeeRequest { @@ -24,13 +26,15 @@ impl FeeRequest { config: NativeRuntimeConfig, state_hash: Digest, protocol_version: ProtocolVersion, - block_time: u64, + block_time: BlockTime, + holds_epoch: HoldsEpoch, ) -> Self { FeeRequest { config, state_hash, protocol_version, block_time, + holds_epoch, } } @@ -55,10 +59,15 @@ impl FeeRequest { } /// Returns block time. - pub fn block_time(&self) -> u64 { + pub fn block_time(&self) -> BlockTime { self.block_time } + /// Returns holds epoch. + pub fn holds_epoch(&self) -> HoldsEpoch { + self.holds_epoch + } + /// Returns administrative accounts, if any. pub fn administrative_accounts(&self) -> Option<&BTreeSet> { match self.config.transfer_config() { @@ -108,7 +117,7 @@ pub enum FeeResult { Failure(FeeError), Success { /// List of transfers that happened during execution. - transfers: Vec, + transfers: Vec, /// State hash after fee distribution outcome is committed to the global state. post_state_hash: Digest, /// Effects of the fee distribution process. diff --git a/storage/src/data_access_layer/handle_payment.rs b/storage/src/data_access_layer/handle_payment.rs new file mode 100644 index 0000000000..4dc9248d60 --- /dev/null +++ b/storage/src/data_access_layer/handle_payment.rs @@ -0,0 +1,141 @@ +use crate::{ + data_access_layer::BalanceIdentifier, system::runtime_native::Config as NativeRuntimeConfig, + tracking_copy::TrackingCopyError, +}; +use casper_types::{ + execution::Effects, Digest, HoldsEpoch, ProtocolVersion, TransactionHash, U512, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum HandlePaymentMode { + Finalize { + limit: U512, + gas_price: u8, + cost: U512, + consumed: U512, + source: Box, + target: Box, + holds_epoch: HoldsEpoch, + }, + Burn { + source: BalanceIdentifier, + amount: Option, + }, + ClearHolds { + source: BalanceIdentifier, + holds_epoch: HoldsEpoch, + }, +} + +impl HandlePaymentMode { + pub fn finalize( + limit: U512, + gas_price: u8, + cost: U512, + consumed: U512, + source: BalanceIdentifier, + target: BalanceIdentifier, + holds_epoch: HoldsEpoch, + ) -> Self { + HandlePaymentMode::Finalize { + limit, + gas_price, + cost, + consumed, + source: Box::new(source), + target: Box::new(target), + holds_epoch, + } + } + + /// What source should be used to burn from, and how much? + /// If amount is None or greater than the available balance, the full available balance + /// will be burned. If amount is less than available balance, only that much will be + /// burned leaving a remaining balance. + pub fn burn(source: BalanceIdentifier, amount: Option) -> Self { + HandlePaymentMode::Burn { source, amount } + } + + /// Clear expired holds against source's balance per epoch. + pub fn clear_holds(source: BalanceIdentifier, holds_epoch: HoldsEpoch) -> Self { + HandlePaymentMode::ClearHolds { + source, + holds_epoch, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HandlePaymentRequest { + /// The runtime config. + pub(crate) config: NativeRuntimeConfig, + /// State root hash. + pub(crate) state_hash: Digest, + /// The protocol version. + pub(crate) protocol_version: ProtocolVersion, + /// Transaction hash. + pub(crate) transaction_hash: TransactionHash, + /// Handle payment mode. + pub(crate) handle_payment_mode: HandlePaymentMode, +} + +impl HandlePaymentRequest { + /// Creates new request instance with runtime args. + #[allow(clippy::too_many_arguments)] + pub fn new( + config: NativeRuntimeConfig, + state_hash: Digest, + protocol_version: ProtocolVersion, + transaction_hash: TransactionHash, + handle_payment_mode: HandlePaymentMode, + ) -> Self { + Self { + config, + state_hash, + protocol_version, + transaction_hash, + handle_payment_mode, + } + } + + pub fn config(&self) -> &NativeRuntimeConfig { + &self.config + } + + pub fn state_hash(&self) -> Digest { + self.state_hash + } + + pub fn protocol_version(&self) -> ProtocolVersion { + self.protocol_version + } + + pub fn transaction_hash(&self) -> TransactionHash { + self.transaction_hash + } + + pub fn handle_payment_mode(&self) -> &HandlePaymentMode { + &self.handle_payment_mode + } +} + +/// Result enum that represents all possible outcomes of a handle payment request. +#[derive(Debug)] +pub enum HandlePaymentResult { + /// Invalid state root hash. + RootNotFound, + /// Handle payment request succeeded. + Success { effects: Effects }, + /// Handle payment request failed. + Failure(TrackingCopyError), +} + +impl HandlePaymentResult { + /// The effects, if any. + pub fn effects(&self) -> Effects { + match self { + HandlePaymentResult::RootNotFound | HandlePaymentResult::Failure(_) => Effects::new(), + HandlePaymentResult::Success { effects, .. } => effects.clone(), + } + } +} diff --git a/storage/src/data_access_layer/transfer.rs b/storage/src/data_access_layer/mint.rs similarity index 71% rename from storage/src/data_access_layer/transfer.rs rename to storage/src/data_access_layer/mint.rs index b20ca9a55b..fe0f32186b 100644 --- a/storage/src/data_access_layer/transfer.rs +++ b/storage/src/data_access_layer/mint.rs @@ -2,8 +2,8 @@ use std::collections::BTreeSet; use crate::system::runtime_native::{Config as NativeRuntimeConfig, TransferConfig}; use casper_types::{ - account::AccountHash, execution::Effects, Digest, ProtocolVersion, RuntimeArgs, - TransactionHash, TransferAddr, U512, + account::AccountHash, execution::Effects, Digest, HoldsEpoch, InitiatorAddr, ProtocolVersion, + RuntimeArgs, TransactionHash, Transfer, }; use crate::system::transfer::{TransferArgs, TransferError}; @@ -22,20 +22,18 @@ pub struct TransferRequest { config: NativeRuntimeConfig, /// State root hash. state_hash: Digest, - /// Block time represented as a unix timestamp. - block_time: u64, + /// Balance holds epoch. + holds_epoch: HoldsEpoch, /// Protocol version. protocol_version: ProtocolVersion, /// Transaction hash. transaction_hash: TransactionHash, /// Base account. - address: AccountHash, + initiator: InitiatorAddr, /// List of authorizing accounts. authorization_keys: BTreeSet, /// Args. args: TransferRequestArgs, - /// Cost. - cost: U512, } impl TransferRequest { @@ -44,25 +42,23 @@ impl TransferRequest { pub fn new( config: NativeRuntimeConfig, state_hash: Digest, - block_time: u64, + holds_epoch: HoldsEpoch, protocol_version: ProtocolVersion, transaction_hash: TransactionHash, - address: AccountHash, + initiator: InitiatorAddr, authorization_keys: BTreeSet, args: TransferArgs, - cost: U512, ) -> Self { let args = TransferRequestArgs::Explicit(args); Self { config, state_hash, - block_time, + holds_epoch, protocol_version, transaction_hash, - address, + initiator, authorization_keys, args, - cost, } } @@ -71,25 +67,23 @@ impl TransferRequest { pub fn with_runtime_args( config: NativeRuntimeConfig, state_hash: Digest, - block_time: u64, + holds_epoch: HoldsEpoch, protocol_version: ProtocolVersion, transaction_hash: TransactionHash, - address: AccountHash, + initiator: InitiatorAddr, authorization_keys: BTreeSet, args: RuntimeArgs, - cost: U512, ) -> Self { let args = TransferRequestArgs::Raw(args); Self { config, state_hash, - block_time, + holds_epoch, protocol_version, transaction_hash, - address, + initiator, authorization_keys, args, - cost, } } @@ -106,9 +100,9 @@ impl TransferRequest { self.state_hash } - /// Returns address. - pub fn address(&self) -> AccountHash { - self.address + /// Returns initiator. + pub fn initiator(&self) -> &InitiatorAddr { + &self.initiator } /// Returns authorization keys. @@ -121,9 +115,9 @@ impl TransferRequest { self.protocol_version } - /// Returns block time. - pub fn block_time(&self) -> u64 { - self.block_time + /// Returns holds epoch. + pub fn holds_epoch(&self) -> HoldsEpoch { + self.holds_epoch } /// Returns transaction hash. @@ -131,11 +125,6 @@ impl TransferRequest { self.transaction_hash } - /// The cost. - pub fn cost(&self) -> U512 { - self.cost - } - /// Returns transfer args. pub fn args(&self) -> &TransferRequestArgs { &self.args @@ -145,6 +134,14 @@ impl TransferRequest { pub fn into_args(self) -> TransferRequestArgs { self.args } + + /// Used by `WasmTestBuilder` to set the appropriate state root hash and transfer config before + /// executing the transfer. + #[doc(hidden)] + pub fn set_state_hash_and_config(&mut self, state_hash: Digest, config: NativeRuntimeConfig) { + self.state_hash = state_hash; + self.config = config; + } } #[derive(Debug, Clone)] @@ -154,10 +151,20 @@ pub enum TransferResult { /// Transfer succeeded Success { /// List of transfers that happened during execution. - transfers: Vec, + transfers: Vec, /// Effects of transfer. effects: Effects, }, /// Transfer failed Failure(TransferError), } + +impl TransferResult { + /// Returns the effects, if any. + pub fn effects(&self) -> Effects { + match self { + TransferResult::RootNotFound | TransferResult::Failure(_) => Effects::new(), + TransferResult::Success { effects, .. } => effects.clone(), + } + } +} diff --git a/storage/src/global_state.rs b/storage/src/global_state.rs index 0443072bab..7e1bd84c7a 100644 --- a/storage/src/global_state.rs +++ b/storage/src/global_state.rs @@ -17,4 +17,4 @@ pub(crate) const DEFAULT_MAX_DB_SIZE: usize = 52_428_800; // 50 MiB pub(crate) const DEFAULT_MAX_READERS: u32 = 512; -pub(crate) const DEFAULT_MAX_QUERY_DEPTH: u64 = 6; +pub(crate) const DEFAULT_MAX_QUERY_DEPTH: u64 = 5; diff --git a/storage/src/global_state/state/mod.rs b/storage/src/global_state/state/mod.rs index f5e01eda8b..5e8cdbb480 100644 --- a/storage/src/global_state/state/mod.rs +++ b/storage/src/global_state/state/mod.rs @@ -6,51 +6,55 @@ pub mod lmdb; /// Lmdb implementation of global state with cache. pub mod scratch; +use itertools::Itertools; use std::{ cell::RefCell, - collections::{BTreeSet, HashMap}, + collections::{BTreeMap, BTreeSet, HashMap}, convert::TryFrom, rc::Rc, }; -use tracing::{debug, error, warn}; -#[cfg(test)] -pub use self::lmdb::make_temporary_global_state; +use tracing::{debug, error, warn}; use casper_types::{ addressable_entity::{EntityKindTag, NamedKeys}, - bytesrepr, - bytesrepr::{FromBytes, ToBytes}, + bytesrepr::{self, ToBytes}, execution::{Effects, TransformError, TransformInstruction, TransformKindV2, TransformV2}, global_state::TrieMerkleProof, - system, system::{ + self, auction::SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, - handle_payment::ACCUMULATION_PURSE_KEY, - mint::{ARG_AMOUNT, ROUND_SEIGNIORAGE_RATE_KEY, TOTAL_SUPPLY_KEY}, - AUCTION, HANDLE_PAYMENT, MINT, + mint::{ + BalanceHoldAddr, BalanceHoldAddrTag, ARG_AMOUNT, ROUND_SEIGNIORAGE_RATE_KEY, + TOTAL_SUPPLY_KEY, + }, + AUCTION, MINT, }, - AccessRights, Account, AddressableEntity, DeployHash, Digest, EntityAddr, Key, KeyTag, Phase, - PublicKey, RuntimeArgs, StoredValue, TransactionHash, TransactionV1Hash, U512, + Account, AddressableEntity, CLValue, Digest, EntityAddr, Key, KeyTag, Phase, PublicKey, + RuntimeArgs, StoredValue, U512, }; +#[cfg(test)] +pub use self::lmdb::make_temporary_global_state; use crate::{ data_access_layer::{ - bidding::{AuctionMethodRet, BiddingRequest, BiddingResult}, + auction::{AuctionMethodRet, BiddingRequest, BiddingResult}, + balance::BalanceHandling, era_validators::EraValidatorsResult, + handle_payment::{HandlePaymentMode, HandlePaymentRequest, HandlePaymentResult}, + mint::{TransferRequest, TransferRequestArgs, TransferResult}, tagged_values::{TaggedValuesRequest, TaggedValuesResult}, - transfer::{TransferRequest, TransferRequestArgs, TransferResult}, - AddressableEntityRequest, AddressableEntityResult, AuctionMethod, BalanceIdentifier, - BalanceRequest, BalanceResult, BidsRequest, BidsResult, BlockRewardsError, - BlockRewardsRequest, BlockRewardsResult, EraValidatorsRequest, - ExecutionResultsChecksumRequest, ExecutionResultsChecksumResult, FeeError, FeeRequest, - FeeResult, FlushRequest, FlushResult, GenesisRequest, GenesisResult, - ProtocolUpgradeRequest, ProtocolUpgradeResult, PruneRequest, PruneResult, PutTrieRequest, - PutTrieResult, QueryRequest, QueryResult, RoundSeigniorageRateRequest, - RoundSeigniorageRateResult, StepError, StepRequest, StepResult, - SystemEntityRegistryPayload, SystemEntityRegistryRequest, SystemEntityRegistryResult, - SystemEntityRegistrySelector, TotalSupplyRequest, TotalSupplyResult, TrieRequest, - TrieResult, EXECUTION_RESULTS_CHECKSUM_NAME, + AddressableEntityRequest, AddressableEntityResult, AuctionMethod, BalanceHoldError, + BalanceHoldRequest, BalanceHoldResult, BalanceIdentifier, BalanceRequest, BalanceResult, + BidsRequest, BidsResult, BlockRewardsError, BlockRewardsRequest, BlockRewardsResult, + EraValidatorsRequest, ExecutionResultsChecksumRequest, ExecutionResultsChecksumResult, + FeeError, FeeRequest, FeeResult, FlushRequest, FlushResult, GenesisRequest, GenesisResult, + InsufficientBalanceHandling, ProtocolUpgradeRequest, ProtocolUpgradeResult, PruneRequest, + PruneResult, PutTrieRequest, PutTrieResult, QueryRequest, QueryResult, + RoundSeigniorageRateRequest, RoundSeigniorageRateResult, StepError, StepRequest, + StepResult, SystemEntityRegistryPayload, SystemEntityRegistryRequest, + SystemEntityRegistryResult, SystemEntityRegistrySelector, TotalSupplyRequest, + TotalSupplyResult, TrieRequest, TrieResult, EXECUTION_RESULTS_CHECKSUM_NAME, }, global_state::{ error::Error as GlobalStateError, @@ -66,12 +70,11 @@ use crate::{ auction, auction::Auction, genesis::{GenesisError, GenesisInstaller}, + handle_payment::HandlePayment, mint::Mint, protocol_upgrade::{ProtocolUpgradeError, ProtocolUpgrader}, - runtime_native::RuntimeNative, - transfer::{ - NewTransferTargetMode, TransferArgs, TransferError, TransferRuntimeArgsBuilder, - }, + runtime_native::{Id, RuntimeNative}, + transfer::{NewTransferTargetMode, TransferError, TransferRuntimeArgsBuilder}, }, tracking_copy::{TrackingCopy, TrackingCopyEntityExt, TrackingCopyError, TrackingCopyExt}, }; @@ -274,7 +277,7 @@ pub trait CommitProvider: StateProvider { } }; - crate::system::runtime_native::Id::Seed(bytes) + Id::Seed(bytes) }; let config = request.config(); @@ -371,7 +374,7 @@ pub trait CommitProvider: StateProvider { } }; - crate::system::runtime_native::Id::Seed(bytes) + Id::Seed(bytes) }; // this runtime uses the system's context @@ -421,13 +424,6 @@ pub trait CommitProvider: StateProvider { }; } - let administrative_accounts = match request.administrative_accounts() { - Some(administrative_accounts) => administrative_accounts, - None => { - return FeeResult::Failure(FeeError::AdministrativeAccountsNotFound); - } - }; - let tc = match self.tracking_copy(state_hash) { Ok(Some(tracking_copy)) => Rc::new(RefCell::new(tracking_copy)), Ok(None) => return FeeResult::RootNotFound, @@ -436,305 +432,72 @@ pub trait CommitProvider: StateProvider { } }; - // need the accumulation purse - let entity_hash = match tc.borrow_mut().get_system_entity_registry() { - Ok(scr) => match scr.get(HANDLE_PAYMENT).copied() { - Some(entity_hash) => entity_hash, - None => { - return FeeResult::Failure(FeeError::RegistryEntryNotFound( - HANDLE_PAYMENT.to_string(), - )) - } - }, - Err(tce) => return FeeResult::Failure(FeeError::TrackingCopy(tce)), - }; - let named_keys = match tc - .borrow_mut() - .get_named_keys(EntityAddr::System(entity_hash.value())) - { - Ok(named_keys) => named_keys, - Err(tce) => return FeeResult::Failure(FeeError::TrackingCopy(tce)), - }; - - let accumulation_purse = match named_keys.get(ACCUMULATION_PURSE_KEY) { - Some(key) => { - if let Key::URef(uref) = key { - *uref - } else { - return FeeResult::Failure(FeeError::TrackingCopy( - TrackingCopyError::UnexpectedKeyVariant(*key), - )); - } - } - None => { - return FeeResult::Failure(FeeError::TrackingCopy( - TrackingCopyError::NamedKeyNotFound(ACCUMULATION_PURSE_KEY.to_string()), - )) - } - }; - + let config = request.config(); let protocol_version = request.protocol_version(); - - let accumulated_balance = { - let balance_req = - BalanceRequest::from_purse(state_hash, protocol_version, accumulation_purse); - let balance_result = self.balance(balance_req); - match balance_result { - BalanceResult::RootNotFound => { - return FeeResult::RootNotFound; - } - BalanceResult::Failure(tce) => { - return FeeResult::Failure(FeeError::TrackingCopy(tce)); - } - BalanceResult::Success { motes, .. } => motes, - } - }; - - let mut current_state_hash = state_hash; - let mut effects = Effects::new(); - let mut transfers = vec![]; - let recipient_count = U512::from(administrative_accounts.len()); - - // distribute fees to administrators - // this is basically just a series of transfers from the accumulated purse to - // configured accounts. this is a behavior used by some (but not all) private chains. - if let Some(fee_portion) = accumulated_balance.checked_div(recipient_count) { - if fee_portion.is_zero() { - // If there are no fees to be paid out, it is effectively noop - return FeeResult::Success { - effects: Effects::default(), - post_state_hash: state_hash, - transfers: vec![], - }; - } - - let system_account_key = PublicKey::System; - let id = { - let mut bytes = match request.block_time().into_bytes() { - Ok(bytes) => bytes, - Err(bre) => { - return FeeResult::Failure(FeeError::TrackingCopy( - TrackingCopyError::BytesRepr(bre), - )) - } - }; - match &mut state_hash.into_bytes() { - Ok(more_bytes) => bytes.append(more_bytes), - Err(bre) => { - return FeeResult::Failure(FeeError::TrackingCopy( - TrackingCopyError::BytesRepr(*bre), - )) - } - }; - - crate::system::runtime_native::Id::Seed(bytes) - }; - - let config = request.config(); - let block_time = request.block_time(); - let authorization_keys = { - let mut auth_keys = BTreeSet::new(); - auth_keys.insert(system_account_key.to_account_hash()); - auth_keys - }; - - // TODO: the transfer logic needs to be tweaked once Fraser's logic w/ version handling - // merges - let tmp_hash = match TransactionV1Hash::from_bytes(&id.seed()) { - Ok((hash, _rem)) => TransactionHash::V1(hash), + let seed = { + let mut bytes = match request.block_time().into_bytes() { + Ok(bytes) => bytes, Err(bre) => { return FeeResult::Failure(FeeError::TrackingCopy( TrackingCopyError::BytesRepr(bre), )) } }; - for target in administrative_accounts { - let target_purse = match tc - .borrow_mut() - .get_addressable_entity_by_account_hash(protocol_version, *target) - { - Ok(entity) => entity.main_purse(), - Err(tce) => return FeeResult::Failure(FeeError::TrackingCopy(tce)), - }; - let args = TransferArgs::new( - Some(*target), - accumulation_purse, - target_purse, - fee_portion, - None, - ); - - let transfer_req = TransferRequest::new( - config.clone(), - current_state_hash, - block_time, - protocol_version, - tmp_hash, - system_account_key.to_account_hash(), - authorization_keys.clone(), - args, - U512::zero(), - ); - match self.transfer(transfer_req) { - TransferResult::RootNotFound => return FeeResult::RootNotFound, - TransferResult::Failure(transfer_error) => { - return FeeResult::Failure(FeeError::Transfer(transfer_error)) - } - TransferResult::Success { - effects: transfer_effects, - transfers: more_transfers, - } => match self.commit(current_state_hash, transfer_effects.clone()) { - Ok(post_state_hash) => { - current_state_hash = post_state_hash; - effects.append(transfer_effects); - transfers.extend(more_transfers); - } - Err(gse) => { - return FeeResult::Failure(FeeError::TrackingCopy( - TrackingCopyError::Storage(gse), - )) - } - }, + match &mut protocol_version.into_bytes() { + Ok(next) => bytes.append(next), + Err(bre) => { + return FeeResult::Failure(FeeError::TrackingCopy( + TrackingCopyError::BytesRepr(*bre), + )) } - } - - return FeeResult::Success { - post_state_hash: current_state_hash, - effects, - transfers, }; - } - FeeResult::Failure(FeeError::NoFeesDistributed) - } - /// Direct biddings. - fn bidding(&self, request: BiddingRequest) -> BiddingResult { - let state_hash = request.state_hash(); - let tc = match self.tracking_copy(state_hash) { - Ok(Some(tc)) => Rc::new(RefCell::new(tc)), - Ok(None) => return BiddingResult::RootNotFound, - Err(err) => return BiddingResult::Failure(TrackingCopyError::Storage(err)), + Id::Seed(bytes) }; - let protocol_version = request.protocol_version(); - let config = request.config(); - let id = crate::system::runtime_native::Id::Transaction(request.transaction_hash()); - - let initiating_address = request.address(); - let authorization_keys = request.authorization_keys(); - let transfer_config = config.transfer_config(); - let administrative_accounts = transfer_config.administrative_accounts(); - let (entity, entity_named_keys, entity_access_rights) = - match tc.borrow_mut().resolved_entity( - protocol_version, - initiating_address, - authorization_keys, - &administrative_accounts, - ) { - Ok(ret) => ret, - Err(tce) => { - return BiddingResult::Failure(tce); - } - }; - - // IMPORTANT: this runtime _must_ use the initiators's context. - let mut runtime = RuntimeNative::new( - protocol_version, + // this runtime uses the system's context + let mut runtime = match RuntimeNative::new_system_runtime( config.clone(), - id, + protocol_version, + seed, Rc::clone(&tc), - initiating_address, - entity, - entity_named_keys, - entity_access_rights, - U512::MAX, - Phase::Session, - ); - - let auction_method = request.auction_method(); - - let result = match auction_method { - AuctionMethod::ActivateBid { - validator_public_key, - } => runtime - .activate_bid(validator_public_key) - .map(|_| AuctionMethodRet::Unit) - .map_err(|auc_err| { - TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) - }), - AuctionMethod::AddBid { - public_key, - delegation_rate, - amount, - } => runtime - .add_bid(public_key, delegation_rate, amount) - .map(AuctionMethodRet::UpdatedAmount) - .map_err(TrackingCopyError::Api), - AuctionMethod::WithdrawBid { public_key, amount } => runtime - .withdraw_bid(public_key, amount) - .map(AuctionMethodRet::UpdatedAmount) - .map_err(|auc_err| { - TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) - }), - AuctionMethod::Delegate { - delegator_public_key, - validator_public_key, - amount, - max_delegators_per_validator, - minimum_delegation_amount, - } => runtime - .delegate( - delegator_public_key, - validator_public_key, - amount, - max_delegators_per_validator, - minimum_delegation_amount, - ) - .map(AuctionMethodRet::UpdatedAmount) - .map_err(TrackingCopyError::Api), - AuctionMethod::Undelegate { - delegator_public_key, - validator_public_key, - amount, - } => runtime - .undelegate(delegator_public_key, validator_public_key, amount) - .map(AuctionMethodRet::UpdatedAmount) - .map_err(|auc_err| { - TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) - }), - AuctionMethod::Redelegate { - delegator_public_key, - validator_public_key, - amount, - new_validator, - minimum_delegation_amount, - } => runtime - .redelegate( - delegator_public_key, - validator_public_key, - amount, - new_validator, - minimum_delegation_amount, - ) - .map(AuctionMethodRet::UpdatedAmount) - .map_err(|auc_err| { - TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) - }), + Phase::System, + ) { + Ok(rt) => rt, + Err(tce) => { + return FeeResult::Failure(FeeError::TrackingCopy(tce)); + } }; - let effects = tc.borrow_mut().effects(); + let source = BalanceIdentifier::Accumulate; + let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) { + Ok(value) => value, + Err(tce) => return FeeResult::Failure(FeeError::TrackingCopy(tce)), + }; + // amount = None will distribute the full current balance of the accumulation purse + let result = runtime.distribute_accumulated_fees(source_purse, None); - // commit match result { - Ok(ret) => match self.commit(state_hash, effects.clone()) { - Ok(post_state_hash) => BiddingResult::Success { - ret, - post_state_hash, + Ok(_) => { + let effects = tc.borrow_mut().effects(); + let transfers = runtime.into_transfers(); + let post_state_hash = match self.commit(state_hash, effects.clone()) { + Ok(post_state_hash) => post_state_hash, + Err(gse) => { + return FeeResult::Failure(FeeError::TrackingCopy( + TrackingCopyError::Storage(gse), + )) + } + }; + FeeResult::Success { effects, - }, - Err(tce) => BiddingResult::Failure(tce.into()), - }, - Err(tce) => BiddingResult::Failure(tce), + transfers, + post_state_hash, + } + } + Err(hpe) => FeeResult::Failure(FeeError::TrackingCopy( + TrackingCopyError::SystemContract(system::Error::HandlePayment(hpe)), + )), } } } @@ -779,44 +542,142 @@ pub trait StateProvider { Err(err) => return BalanceResult::Failure(TrackingCopyError::Storage(err)), }; let protocol_version = request.protocol_version(); - let purse_uref = match request.identifier() { - BalanceIdentifier::Purse(purse_uref) => *purse_uref, - BalanceIdentifier::Public(public_key) => { - let account_hash = public_key.to_account_hash(); - match tc.get_addressable_entity_by_account_hash(protocol_version, account_hash) { - Ok(entity) => entity.main_purse(), + let balance_identifier = request.identifier(); + let purse_key = match balance_identifier.purse_uref(&mut tc, protocol_version) { + Ok(value) => value.into(), + Err(tce) => return BalanceResult::Failure(tce), + }; + let (purse_balance_key, purse_addr) = match tc.get_purse_balance_key(purse_key) { + Ok(key @ Key::Balance(addr)) => (key, addr), + Ok(key) => return BalanceResult::Failure(TrackingCopyError::UnexpectedKeyVariant(key)), + Err(tce) => return BalanceResult::Failure(tce), + }; + + let (total_balance, total_balance_proof) = + match tc.get_total_balance_with_proof(purse_balance_key) { + Err(tce) => return BalanceResult::Failure(tce), + Ok((balance, proof)) => (balance, Box::new(proof)), + }; + + let balance_holds = match request.balance_handling() { + BalanceHandling::Total => BTreeMap::new(), + BalanceHandling::Available { holds_epoch } => { + match tc.get_balance_holds_with_proof(purse_addr, holds_epoch) { Err(tce) => return BalanceResult::Failure(tce), + Ok(holds) => holds, } } - BalanceIdentifier::Account(account_hash) => { - match tc.get_addressable_entity_by_account_hash(protocol_version, *account_hash) { - Ok(entity) => entity.main_purse(), - Err(tce) => return BalanceResult::Failure(tce), - } + }; + + let available_balance = if balance_holds.is_empty() { + total_balance + } else { + let held = balance_holds + .values() + .flat_map(|holds| holds.values().map(|(v, _)| *v)) + .collect_vec() + .into_iter() + .sum(); + + debug_assert!( + total_balance >= held, + "it should not be possible to hold more than the total available" + ); + if held > total_balance { + error!(%held, %total_balance, "holds somehow exceed total balance, which should never occur."); } - BalanceIdentifier::Entity(entity_addr) => { - match tc.get_addressable_entity(*entity_addr) { - Ok(entity) => entity.main_purse(), - Err(tce) => return BalanceResult::Failure(tce), - } + total_balance.checked_sub(held).unwrap_or(U512::zero()) + }; + + BalanceResult::Success { + purse_addr, + total_balance, + total_balance_proof, + available_balance, + balance_holds, + } + } + + /// Balance hold. + fn balance_hold(&self, request: BalanceHoldRequest) -> BalanceHoldResult { + let mut tc = match self.tracking_copy(request.state_hash()) { + Ok(Some(tracking_copy)) => tracking_copy, + Ok(None) => return BalanceHoldResult::RootNotFound, + Err(err) => { + return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy( + TrackingCopyError::Storage(err), + )) } - BalanceIdentifier::Internal(addr) => casper_types::URef::new(*addr, AccessRights::READ), }; - let purse_key = purse_uref.into(); - // read the new hold records if any exist - // check their timestamps..if stale tc.prune(that item) - // total bal - sum(hold balance) == avail - match tc.get_purse_balance_key(purse_key) { - Ok(purse_balance_key) => match tc.get_purse_balance_with_proof(purse_balance_key) { - Ok((balance, proof)) => { - let proof = Box::new(proof); - let motes = balance.value(); - BalanceResult::Success { motes, proof } - } - Err(err) => BalanceResult::Failure(err), + let balance_request = request.clone().into(); + let balance_result = self.balance(balance_request); + let (total_balance, remaining_balance, purse_addr) = match balance_result { + BalanceResult::RootNotFound => return BalanceHoldResult::RootNotFound, + BalanceResult::Failure(tce) => { + return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy(tce)) + } + BalanceResult::Success { + total_balance, + available_balance, + purse_addr, + .. + } => (total_balance, available_balance, purse_addr), + }; + + let held_amount = { + if remaining_balance >= request.hold_amount() { + // the purse has sufficient balance to fully cover the hold + request.hold_amount() + } else if request.insufficient_handling() == InsufficientBalanceHandling::Noop { + // the purse has insufficient balance but the holding mode is noop, so get out + return BalanceHoldResult::Failure(BalanceHoldError::InsufficientBalance { + remaining_balance, + }); + } else { + // currently this is always the default HoldRemaining variant. + // the purse holder has insufficient balance to cover the hold, + // but the system will put a hold on whatever balance remains. + // this is basically punitive to block an edge case resource consumption + // attack whereby a malicious purse holder drains a balance to not-zero + // but not-enough-to-cover-holds and then spams a bunch of transactions + // knowing that they will fail due to insufficient funds, but only + // after making the system do the work of processing the balance + // check without penalty to themselves. + remaining_balance + } + }; + + let cl_value = match CLValue::from_t(held_amount) { + Ok(cl_value) => cl_value, + Err(cve) => { + return BalanceHoldResult::Failure(BalanceHoldError::TrackingCopy( + TrackingCopyError::CLValue(cve), + )) + } + }; + + let balance_hold_addr = match request.hold_kind() { + BalanceHoldAddrTag::Gas => BalanceHoldAddr::Gas { + purse_addr, + block_time: request.block_time(), }, - Err(err) => BalanceResult::Failure(err), - } + }; + + tc.write( + Key::BalanceHold(balance_hold_addr), + StoredValue::CLValue(cl_value), + ); + + let available_balance = remaining_balance.saturating_sub(held_amount); + let effects = tc.effects(); + + BalanceHoldResult::success( + total_balance, + available_balance, + request.hold_amount(), + held_amount, + effects, + ) } /// Get the requested era validators. @@ -913,6 +774,227 @@ pub trait StateProvider { BidsResult::Success { bids } } + /// Direct auction interaction for all variations of bid management. + fn bidding( + &self, + BiddingRequest { + config, + state_hash, + protocol_version, + auction_method, + transaction_hash, + initiator, + authorization_keys, + }: BiddingRequest, + ) -> BiddingResult { + let tc = match self.tracking_copy(state_hash) { + Ok(Some(tc)) => Rc::new(RefCell::new(tc)), + Ok(None) => return BiddingResult::RootNotFound, + Err(err) => return BiddingResult::Failure(TrackingCopyError::Storage(err)), + }; + + let source_account_hash = initiator.account_hash(); + let (entity, entity_named_keys, entity_access_rights) = + match tc.borrow_mut().resolved_entity( + protocol_version, + source_account_hash, + &authorization_keys, + &BTreeSet::default(), + ) { + Ok(ret) => ret, + Err(tce) => { + return BiddingResult::Failure(tce); + } + }; + + // IMPORTANT: this runtime _must_ use the payer's context. + let mut runtime = RuntimeNative::new( + config, + protocol_version, + Id::Transaction(transaction_hash), + Rc::clone(&tc), + source_account_hash, + entity, + entity_named_keys, + entity_access_rights, + U512::MAX, + Phase::Session, + ); + + let result = match auction_method { + AuctionMethod::ActivateBid { validator } => runtime + .activate_bid(validator) + .map(|_| AuctionMethodRet::Unit) + .map_err(|auc_err| { + TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) + }), + AuctionMethod::AddBid { + public_key, + delegation_rate, + amount, + holds_epoch, + } => runtime + .add_bid(public_key, delegation_rate, amount, holds_epoch) + .map(AuctionMethodRet::UpdatedAmount) + .map_err(TrackingCopyError::Api), + AuctionMethod::WithdrawBid { public_key, amount } => runtime + .withdraw_bid(public_key, amount) + .map(AuctionMethodRet::UpdatedAmount) + .map_err(|auc_err| { + TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) + }), + AuctionMethod::Delegate { + delegator, + validator, + amount, + max_delegators_per_validator, + minimum_delegation_amount, + holds_epoch, + } => runtime + .delegate( + delegator, + validator, + amount, + max_delegators_per_validator, + minimum_delegation_amount, + holds_epoch, + ) + .map(AuctionMethodRet::UpdatedAmount) + .map_err(TrackingCopyError::Api), + AuctionMethod::Undelegate { + delegator, + validator, + amount, + } => runtime + .undelegate(delegator, validator, amount) + .map(AuctionMethodRet::UpdatedAmount) + .map_err(|auc_err| { + TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) + }), + AuctionMethod::Redelegate { + delegator, + validator, + amount, + new_validator, + minimum_delegation_amount, + } => runtime + .redelegate( + delegator, + validator, + amount, + new_validator, + minimum_delegation_amount, + ) + .map(AuctionMethodRet::UpdatedAmount) + .map_err(|auc_err| { + TrackingCopyError::SystemContract(system::Error::Auction(auc_err)) + }), + }; + + let effects = tc.borrow_mut().effects(); + + match result { + Ok(ret) => BiddingResult::Success { ret, effects }, + Err(tce) => BiddingResult::Failure(tce), + } + } + + /// Direct auction interaction for all variations of bid management. + fn handle_payment( + &self, + HandlePaymentRequest { + config, + state_hash, + protocol_version, + transaction_hash, + handle_payment_mode, + }: HandlePaymentRequest, + ) -> HandlePaymentResult { + let tc = match self.tracking_copy(state_hash) { + Ok(Some(tc)) => Rc::new(RefCell::new(tc)), + Ok(None) => return HandlePaymentResult::RootNotFound, + Err(err) => return HandlePaymentResult::Failure(TrackingCopyError::Storage(err)), + }; + + // this runtime uses the system's context + let mut runtime = match RuntimeNative::new_system_runtime( + config, + protocol_version, + Id::Transaction(transaction_hash), + Rc::clone(&tc), + Phase::Session, + ) { + Ok(rt) => rt, + Err(tce) => { + return HandlePaymentResult::Failure(tce); + } + }; + + let result = match handle_payment_mode { + HandlePaymentMode::Finalize { + limit, + gas_price, + cost, + consumed, + source, + target, + holds_epoch, + } => { + let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) { + Ok(value) => value, + Err(tce) => return HandlePaymentResult::Failure(tce), + }; + let target_purse = match target.purse_uref(&mut tc.borrow_mut(), protocol_version) { + Ok(value) => value, + Err(tce) => return HandlePaymentResult::Failure(tce), + }; + runtime.finalize_payment( + limit, + gas_price, + cost, + consumed, + source_purse, + target_purse, + holds_epoch, + ) + } + HandlePaymentMode::Burn { source, amount } => { + let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) { + Ok(value) => value, + Err(tce) => return HandlePaymentResult::Failure(tce), + }; + runtime.burn(source_purse, amount) + } + HandlePaymentMode::ClearHolds { + source, + holds_epoch, + } => { + let tag = BalanceHoldAddrTag::Gas; + let source_purse = match source.purse_uref(&mut tc.borrow_mut(), protocol_version) { + Ok(value) => value, + Err(tce) => return HandlePaymentResult::Failure(tce), + }; + if let Err(tce) = tc.borrow_mut().clear_expired_balance_holds( + source_purse.addr(), + tag, + holds_epoch, + ) { + return HandlePaymentResult::Failure(tce); + } + Ok(()) + } + }; + + let effects = tc.borrow_mut().effects(); + + match result { + Ok(_) => HandlePaymentResult::Success { effects }, + Err(hpe) => HandlePaymentResult::Failure(TrackingCopyError::SystemContract( + system::Error::HandlePayment(hpe), + )), + } + } + /// Gets the execution result checksum. fn execution_result_checksum( &self, @@ -1207,7 +1289,7 @@ pub trait StateProvider { } }; - let source_account_hash = request.address(); + let source_account_hash = request.initiator().account_hash(); let protocol_version = request.protocol_version(); if let Err(tce) = tc .borrow_mut() @@ -1288,11 +1370,11 @@ pub trait StateProvider { } }; - let id = crate::system::runtime_native::Id::Transaction(request.transaction_hash()); + let id = Id::Transaction(request.transaction_hash()); // IMPORTANT: this runtime _must_ use the payer's context. let mut runtime = RuntimeNative::new( - protocol_version, config.clone(), + protocol_version, id, Rc::clone(&tc), source_account_hash, @@ -1327,16 +1409,14 @@ pub trait StateProvider { } } - let transfer_args = { - match runtime_args_builder.build( - &entity, - entity_named_keys, - protocol_version, - Rc::clone(&tc), - ) { - Ok(transfer_args) => transfer_args, - Err(error) => return TransferResult::Failure(error), - } + let transfer_args = match runtime_args_builder.build( + &entity, + entity_named_keys, + protocol_version, + Rc::clone(&tc), + ) { + Ok(transfer_args) => transfer_args, + Err(error) => return TransferResult::Failure(error), }; if let Err(mint_error) = runtime.transfer( transfer_args.to(), @@ -1344,28 +1424,13 @@ pub trait StateProvider { transfer_args.target(), transfer_args.amount(), transfer_args.arg_id(), + request.holds_epoch(), ) { return TransferResult::Failure(TransferError::Mint(mint_error)); } let transfers = runtime.into_transfers(); - { - // TODO: this lexical block needs to be updated with the new versioned transaction types - let deploy_hash = DeployHash::new(request.transaction_hash().digest()); - let deploy_info = casper_types::DeployInfo::new( - deploy_hash, - &transfers, - source_account_hash, - entity.main_purse(), - request.cost(), - ); - tc.borrow_mut().write( - Key::DeployInfo(deploy_hash), - StoredValue::DeployInfo(deploy_info), - ); - } - let effects = tc.borrow_mut().effects(); TransferResult::Success { transfers, effects } diff --git a/storage/src/lib.rs b/storage/src/lib.rs index e60553da2b..71c7918515 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -18,5 +18,10 @@ pub mod tracking_copy; pub use address_generator::{AddressGenerator, AddressGeneratorBuilder}; pub use tracking_copy::TrackingCopy; +pub use block_store::{ + lmdb::{DbTableId, UnknownDbTableId}, + DbRawBytesSpec, +}; + #[cfg(test)] pub use self::tracking_copy::new_temporary_tracking_copy; diff --git a/storage/src/system/auction.rs b/storage/src/system/auction.rs index 61b2b8e44f..38eaafc7b9 100644 --- a/storage/src/system/auction.rs +++ b/storage/src/system/auction.rs @@ -18,7 +18,7 @@ use casper_types::{ BidAddr, BidKind, DelegationRate, EraInfo, EraValidators, Error, SeigniorageRecipients, UnbondingPurse, ValidatorBid, ValidatorWeights, DELEGATION_RATE_DENOMINATOR, }, - ApiError, EraId, PublicKey, U512, + ApiError, EraId, HoldsEpoch, PublicKey, U512, }; use self::providers::{AccountProvider, MintProvider, RuntimeProvider, StorageProvider}; @@ -69,15 +69,14 @@ pub trait Auction: public_key: PublicKey, delegation_rate: DelegationRate, amount: U512, + holds_epoch: HoldsEpoch, ) -> Result { if !self.allow_auction_bids() { - // Validation set rotation might be disabled on some private chains and we should not - // allow new bids to come in. + // The validator set may be closed on some side chains, + // which is configured by disabling bids. return Err(Error::AuctionBidsDisabled.into()); } - let provided_account_hash = AccountHash::from_public_key(&public_key, |x| self.blake2b(x)); - if amount.is_zero() { return Err(Error::BondTooSmall.into()); } @@ -86,6 +85,8 @@ pub trait Auction: return Err(Error::DelegationRateTooLarge.into()); } + let provided_account_hash = AccountHash::from_public_key(&public_key, |x| self.blake2b(x)); + if !self.is_allowed_session_caller(&provided_account_hash) { return Err(Error::InvalidContext.into()); } @@ -94,6 +95,9 @@ pub trait Auction: let (target, validator_bid) = if let Some(BidKind::Validator(mut validator_bid)) = self.read_bid(&validator_bid_key)? { + if validator_bid.inactive() { + validator_bid.activate(); + } validator_bid.increase_stake(amount)?; validator_bid.with_delegation_rate(delegation_rate); (*validator_bid.bonding_purse(), validator_bid) @@ -111,6 +115,7 @@ pub trait Auction: target, amount, None, + holds_epoch, ) .map_err(|_| Error::TransferToBidPurse)? .map_err(|mint_error| { @@ -208,6 +213,7 @@ pub trait Auction: amount: U512, max_delegators_per_validator: u32, minimum_delegation_amount: u64, + holds_epoch: HoldsEpoch, ) -> Result { if !self.allow_auction_bids() { // Validation set rotation might be disabled on some private chains and we should not @@ -229,6 +235,7 @@ pub trait Auction: amount, max_delegators_per_validator, minimum_delegation_amount, + holds_epoch, ) } @@ -683,15 +690,14 @@ pub trait Auction: /// Activates a given validator's bid. To be used when a validator has been marked as inactive /// by consensus (aka "evicted"). - fn activate_bid(&mut self, validator_public_key: PublicKey) -> Result<(), Error> { - let provided_account_hash = - AccountHash::from_public_key(&validator_public_key, |x| self.blake2b(x)); + fn activate_bid(&mut self, validator: PublicKey) -> Result<(), Error> { + let provided_account_hash = AccountHash::from_public_key(&validator, |x| self.blake2b(x)); if !self.is_allowed_session_caller(&provided_account_hash) { return Err(Error::InvalidContext); } - let key = BidAddr::from(validator_public_key).into(); + let key = BidAddr::from(validator).into(); if let Some(BidKind::Validator(mut validator_bid)) = self.read_bid(&key)? { validator_bid.activate(); self.write_bid(key, BidKind::Validator(validator_bid))?; diff --git a/storage/src/system/auction/auction_native.rs b/storage/src/system/auction/auction_native.rs index 4c5a0699df..3cc0698a15 100644 --- a/storage/src/system/auction/auction_native.rs +++ b/storage/src/system/auction/auction_native.rs @@ -18,7 +18,7 @@ use casper_types::{ auction::{BidAddr, BidKind, EraInfo, Error, UnbondingPurse}, mint, }, - CLTyped, CLValue, Key, KeyTag, PublicKey, StoredValue, URef, U512, + CLTyped, CLValue, HoldsEpoch, Key, KeyTag, PublicKey, StoredValue, URef, U512, }; use std::collections::BTreeSet; use tracing::error; @@ -142,7 +142,6 @@ where } Ok(None) => Ok(None), Err(TrackingCopyError::BytesRepr(_)) => Err(Error::Serialization), - Err(TrackingCopyError::GasLimit) => Err(Error::GasLimit), Err(err) => { error!("StorageProvider::read_bid: {:?}", err); Err(Error::Storage) @@ -174,7 +173,6 @@ where } Ok(None) => Ok(Vec::new()), Err(TrackingCopyError::BytesRepr(_)) => Err(Error::Serialization), - Err(TrackingCopyError::GasLimit) => Err(Error::GasLimit), Err(err) => { error!("StorageProvider::read_unbonds: {:?}", err); Err(Error::Storage) @@ -256,6 +254,7 @@ where contract.main_purse(), *unbonding_purse.amount(), None, + HoldsEpoch::NOT_APPLICABLE, // unbonding purses do not have holds on them ) .map_err(|_| Error::Transfer)? .map_err(|_| Error::Transfer)?; @@ -273,6 +272,7 @@ where target: URef, amount: U512, id: Option, + holds_epoch: HoldsEpoch, ) -> Result, Error> { if !(self.addressable_entity().main_purse().addr() == source.addr() || self.get_caller() == PublicKey::System.to_account_hash()) @@ -283,7 +283,7 @@ where // let gas_counter = self.gas_counter(); self.extend_access_rights(&[source, target.into_add()]); - match self.transfer(to, source, target, amount, id) { + match self.transfer(to, source, target, amount, id, holds_epoch) { Ok(ret) => { // self.set_gas_counter(gas_counter); Ok(Ok(ret)) @@ -328,8 +328,12 @@ where } } - fn get_balance(&mut self, purse: URef) -> Result, Error> { - match ::balance(self, purse) { + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { + match ::balance(self, purse, holds_epoch) { Ok(ret) => Ok(ret), Err(err) => { error!("{}", err); diff --git a/storage/src/system/auction/detail.rs b/storage/src/system/auction/detail.rs index 38b8a1d869..b7f43fe563 100644 --- a/storage/src/system/auction/detail.rs +++ b/storage/src/system/auction/detail.rs @@ -11,7 +11,7 @@ use casper_types::{ ValidatorBids, AUCTION_DELAY_KEY, ERA_END_TIMESTAMP_MILLIS_KEY, ERA_ID_KEY, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, UNBONDING_DELAY_KEY, VALIDATOR_SLOTS_KEY, }, - ApiError, CLTyped, EraId, Key, KeyTag, PublicKey, URef, U512, + ApiError, CLTyped, EraId, HoldsEpoch, Key, KeyTag, PublicKey, URef, U512, }; use tracing::{error, warn}; @@ -24,7 +24,13 @@ where P: StorageProvider + RuntimeProvider + ?Sized, T: FromBytes + CLTyped, { - let key = provider.named_keys_get(name).ok_or(Error::MissingKey)?; + let key = match provider.named_keys_get(name) { + None => { + error!("auction missing named key {:?}", name); + return Err(Error::MissingKey); + } + Some(key) => key, + }; let uref = key.into_uref().ok_or(Error::InvalidKeyVariant)?; let value: T = provider.read(uref)?.ok_or(Error::MissingValue)?; Ok(value) @@ -270,7 +276,11 @@ pub fn create_unbonding_purse( amount: U512, new_validator: Option, ) -> Result<(), Error> { - if provider.get_balance(bonding_purse)?.unwrap_or_default() < amount { + if provider + .available_balance(bonding_purse, HoldsEpoch::NOT_APPLICABLE)? + .unwrap_or_default() + < amount + { return Err(Error::UnbondTooLarge); } @@ -453,6 +463,7 @@ where *unbonding_purse.amount(), max_delegators_per_validator, minimum_delegation_amount, + HoldsEpoch::NOT_APPLICABLE, ); match redelegation { Ok(_) => Ok(UnbondRedelegationOutcome::SuccessfullyRedelegated), @@ -475,6 +486,7 @@ where /// If specified validator exists, and if validator is not yet at max delegators count, processes /// delegation. For a new delegation a delegator bid record will be created to track the delegation, /// otherwise the existing tracking record will be updated. +#[allow(clippy::too_many_arguments)] pub fn handle_delegation

( provider: &mut P, delegator_public_key: PublicKey, @@ -483,6 +495,7 @@ pub fn handle_delegation

( amount: U512, max_delegators_per_validator: u32, minimum_delegation_amount: u64, + holds_epoch: HoldsEpoch, ) -> Result where P: StorageProvider + MintProvider + RuntimeProvider, @@ -538,6 +551,7 @@ where target, amount, None, + holds_epoch, ) .map_err(|_| Error::TransferToDelegatorPurse)? .map_err(|mint_error| { diff --git a/storage/src/system/auction/providers.rs b/storage/src/system/auction/providers.rs index 2e2c25075f..ff795d499b 100644 --- a/storage/src/system/auction/providers.rs +++ b/storage/src/system/auction/providers.rs @@ -8,7 +8,7 @@ use casper_types::{ auction::{BidAddr, BidKind, EraInfo, Error, UnbondingPurse}, mint, }, - CLTyped, Key, KeyTag, URef, BLAKE2B_DIGEST_LENGTH, U512, + CLTyped, HoldsEpoch, Key, KeyTag, URef, BLAKE2B_DIGEST_LENGTH, U512, }; /// Provider of runtime host functionality. @@ -91,6 +91,7 @@ pub trait MintProvider { target: URef, amount: U512, id: Option, + holds_epoch: HoldsEpoch, ) -> Result, Error>; /// Mint `amount` new token into `existing_purse`. @@ -102,7 +103,11 @@ pub trait MintProvider { fn create_purse(&mut self) -> Result; /// Gets purse balance. - fn get_balance(&mut self, purse: URef) -> Result, Error>; + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error>; /// Reads the base round reward. fn read_base_round_reward(&mut self) -> Result; diff --git a/storage/src/system/error.rs b/storage/src/system/error.rs index 6c18a2af9d..8fc7058bf0 100644 --- a/storage/src/system/error.rs +++ b/storage/src/system/error.rs @@ -3,6 +3,6 @@ use casper_types::account::AccountHash; /// Implementation level errors for system contract providers #[derive(Debug)] pub enum ProviderError { - SystemContractRegistry, + SystemEntityRegistry, AddressableEntityByAccountHash(AccountHash), } diff --git a/storage/src/system/genesis.rs b/storage/src/system/genesis.rs index fee953b703..727f5d3396 100644 --- a/storage/src/system/genesis.rs +++ b/storage/src/system/genesis.rs @@ -24,7 +24,6 @@ use casper_types::{ }, bytesrepr, execution::Effects, - package::{EntityVersions, Groups, PackageStatus}, system::{ auction::{ self, BidAddr, BidKind, DelegationRate, Delegator, SeigniorageRecipient, @@ -39,10 +38,10 @@ use casper_types::{ }, AccessRights, AddressableEntity, AddressableEntityHash, AdministratorAccount, ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind, CLValue, Chainspec, ChainspecRegistry, Digest, - EntityAddr, EntryPoints, EraId, FeeHandling, GenesisAccount, GenesisConfig, - GenesisConfigBuilder, Key, Motes, Package, PackageHash, Phase, ProtocolVersion, PublicKey, - RefundHandling, StoredValue, SystemConfig, SystemEntityRegistry, Tagged, URef, WasmConfig, - U512, + EntityAddr, EntityVersions, EntryPoints, EraId, FeeHandling, GenesisAccount, GenesisConfig, + GenesisConfigBuilder, Groups, Key, Motes, Package, PackageHash, PackageStatus, Phase, + ProtocolVersion, PublicKey, RefundHandling, StoredValue, SystemConfig, SystemEntityRegistry, + Tagged, URef, WasmConfig, U512, }; use crate::{ @@ -288,7 +287,7 @@ where EntityKind::System(SystemEntityType::HandlePayment), )?; - self.store_system_contract_registry(HANDLE_PAYMENT, contract_hash)?; + self.store_system_entity_registry(HANDLE_PAYMENT, contract_hash)?; Ok(contract_hash) } @@ -556,7 +555,7 @@ where EntityKind::System(SystemEntityType::Auction), )?; - self.store_system_contract_registry(AUCTION, contract_hash)?; + self.store_system_entity_registry(AUCTION, contract_hash)?; Ok(contract_hash) } @@ -750,11 +749,9 @@ where .write(byte_code_key, StoredValue::ByteCode(byte_code)); let entity_addr = match entity_kind.tag() { - EntityKindTag::System => EntityAddr::new_system_entity_addr(entity_hash.value()), - EntityKindTag::Account => EntityAddr::new_account_entity_addr(entity_hash.value()), - EntityKindTag::SmartContract => { - EntityAddr::new_contract_entity_addr(entity_hash.value()) - } + EntityKindTag::System => EntityAddr::new_system(entity_hash.value()), + EntityKindTag::Account => EntityAddr::new_account(entity_hash.value()), + EntityKindTag::SmartContract => EntityAddr::new_smart_contract(entity_hash.value()), }; let entity_key: Key = entity_addr.into(); @@ -785,7 +782,7 @@ where contract_hash: AddressableEntityHash, named_keys: NamedKeys, ) -> Result<(), Box> { - let entity_addr = EntityAddr::new_system_entity_addr(contract_hash.value()); + let entity_addr = EntityAddr::new_system(contract_hash.value()); for (string, key) in named_keys.iter() { let named_key_entry = NamedKeyAddr::new_from_string(entity_addr, string.clone()) @@ -804,7 +801,7 @@ where Ok(()) } - fn store_system_contract_registry( + fn store_system_entity_registry( &self, contract_name: &str, contract_hash: AddressableEntityHash, @@ -904,13 +901,12 @@ mod tests { let secret_key = SecretKey::ed25519_from_bytes(bytes).unwrap(); let public_key: PublicKey = PublicKey::from(&secret_key); - let genesis_account_1 = - GenesisAccount::account(public_key.clone(), Motes::new(U512::from(100)), None); + let genesis_account_1 = GenesisAccount::account(public_key.clone(), Motes::new(100), None); bytesrepr::test_serialization_roundtrip(&genesis_account_1); let genesis_account_2 = - GenesisAccount::account(public_key, Motes::new(U512::from(100)), Some(rng.gen())); + GenesisAccount::account(public_key, Motes::new(100), Some(rng.gen())); bytesrepr::test_serialization_roundtrip(&genesis_account_2); } @@ -931,7 +927,7 @@ mod tests { let genesis_account = GenesisAccount::delegator( validator_public_key, delegator_public_key, - Motes::new(U512::from(100)), + Motes::new(100), Motes::zero(), ); diff --git a/storage/src/system/handle_payment.rs b/storage/src/system/handle_payment.rs index 1624bd62d2..fcced771c6 100644 --- a/storage/src/system/handle_payment.rs +++ b/storage/src/system/handle_payment.rs @@ -1,9 +1,10 @@ +mod handle_payment_native; mod internal; pub mod mint_provider; pub mod runtime_provider; pub mod storage_provider; -use casper_types::{account::AccountHash, system::handle_payment::Error, AccessRights, URef, U512}; +use casper_types::{system::handle_payment::Error, AccessRights, HoldsEpoch, URef, U512}; use crate::system::handle_payment::{ mint_provider::MintProvider, runtime_provider::RuntimeProvider, @@ -34,17 +35,39 @@ pub trait HandlePayment: MintProvider + RuntimeProvider + StorageProvider + Size } /// Finalize payment with `amount_spent` and a given `account`. + #[allow(clippy::too_many_arguments)] fn finalize_payment( &mut self, - amount_spent: U512, - account: AccountHash, - target: URef, + limit: U512, + gas_price: u8, + cost: U512, + consumed: U512, + source_purse: URef, + target_purse: URef, + holds_epoch: HoldsEpoch, ) -> Result<(), Error> { - internal::finalize_payment(self, amount_spent, account, target) + internal::finalize_payment( + self, + limit, + gas_price, + cost, + consumed, + source_purse, + target_purse, + holds_epoch, + ) } /// Distribute fees from an accumulation purse. - fn distribute_accumulated_fees(&mut self) -> Result<(), Error> { - internal::distribute_accumulated_fees(self) + fn distribute_accumulated_fees( + &mut self, + source_uref: URef, + amount: Option, + ) -> Result<(), Error> { + internal::distribute_accumulated_fees(self, source_uref, amount) + } + + fn burn(&mut self, source_uref: URef, amount: Option) -> Result<(), Error> { + internal::burn(self, source_uref, amount) } } diff --git a/storage/src/system/handle_payment/handle_payment_native.rs b/storage/src/system/handle_payment/handle_payment_native.rs new file mode 100644 index 0000000000..6e8d7b4f38 --- /dev/null +++ b/storage/src/system/handle_payment/handle_payment_native.rs @@ -0,0 +1,230 @@ +use crate::{ + global_state::{error::Error as GlobalStateError, state::StateReader}, + system::{ + handle_payment::{ + mint_provider::MintProvider, runtime_provider::RuntimeProvider, + storage_provider::StorageProvider, HandlePayment, + }, + mint::Mint, + runtime_native::RuntimeNative, + }, + tracking_copy::TrackingCopyEntityExt, +}; +use casper_types::{ + account::AccountHash, + addressable_entity::{NamedKeyAddr, NamedKeyValue}, + system::handle_payment::Error, + AccessRights, AddressableEntityHash, CLValue, FeeHandling, GrantedAccess, HoldsEpoch, Key, + Phase, RefundHandling, StoredValue, TransferredTo, URef, U512, +}; +use std::collections::BTreeSet; +use tracing::error; + +pub use casper_types::system::handle_payment::Error as HandlePaymentError; + +impl MintProvider for RuntimeNative +where + S: StateReader, +{ + fn transfer_purse_to_account( + &mut self, + source: URef, + target: AccountHash, + amount: U512, + ) -> Result { + let target_key = Key::Account(target); + let entity_key_value = match self.tracking_copy().borrow_mut().read(&target_key) { + Ok(Some(StoredValue::CLValue(cl_value))) => cl_value, // entity exists + Ok(Some(StoredValue::Account(_))) => { + // legacy account exists; attempt to migrate to entity + self.tracking_copy() + .borrow_mut() + .migrate_account(target, self.protocol_version()) + .map_err(|_| Error::Transfer)?; + // attempt to read back migrated entity + if let Ok(Some(StoredValue::CLValue(cl_value))) = + self.tracking_copy().borrow_mut().read(&target_key) + { + cl_value + } else { + return Err(Error::Transfer); + } + } + Ok(_) | Err(_) => return Err(Error::Transfer), + }; + + let entity_key = CLValue::into_t::(entity_key_value) + .map_err(|_| Error::FailedTransferToAccountPurse)?; + // get entity + let target_uref = { + if let Ok(Some(StoredValue::AddressableEntity(entity))) = + self.tracking_copy().borrow_mut().read(&entity_key) + { + entity.main_purse_add_only() + } else { + return Err(Error::Transfer); + } + }; + + // source and target are the same, noop + if source.with_access_rights(AccessRights::ADD) == target_uref { + return Ok(TransferredTo::ExistingAccount); + } + + // Temporarily grant ADD access to target if it is not already present. + let granted_access = self.access_rights_mut().grant_access(target_uref); + + let transfered = self + .transfer_purse_to_purse(source, target_uref, amount) + .is_ok(); + + // if ADD access was temporarily granted, remove it. + if let GrantedAccess::Granted { + uref_addr, + newly_granted_access_rights, + } = granted_access + { + self.access_rights_mut() + .remove_access(uref_addr, newly_granted_access_rights) + } + + if transfered { + Ok(TransferredTo::ExistingAccount) + } else { + Err(Error::Transfer) + } + } + + fn transfer_purse_to_purse( + &mut self, + source: URef, + target: URef, + amount: U512, + ) -> Result<(), Error> { + // system purses do not have holds on them + match self.transfer( + None, + source, + target, + amount, + None, + HoldsEpoch::NOT_APPLICABLE, + ) { + Ok(ret) => Ok(ret), + Err(err) => { + error!("{}", err); + Err(Error::Transfer) + } + } + } + + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { + match ::balance(self, purse, holds_epoch) { + Ok(ret) => Ok(ret), + Err(err) => { + error!("{}", err); + Err(Error::GetBalance) + } + } + } + + fn reduce_total_supply(&mut self, amount: U512) -> Result<(), Error> { + match ::reduce_total_supply(self, amount) { + Ok(ret) => Ok(ret), + Err(err) => { + error!("{}", err); + Err(Error::ReduceTotalSupply) + } + } + } +} + +impl RuntimeProvider for RuntimeNative +where + S: StateReader, +{ + fn get_key(&mut self, name: &str) -> Option { + self.named_keys().get(name).cloned() + } + + fn put_key(&mut self, name: &str, key: Key) -> Result<(), Error> { + let name = name.to_string(); + let entity = self.addressable_entity(); + let addressable_entity_hash = AddressableEntityHash::new(self.address().value()); + let entity_addr = entity.entity_addr(addressable_entity_hash); + let named_key_value = StoredValue::NamedKey( + NamedKeyValue::from_concrete_values(key, name.clone()).map_err(|_| Error::PutKey)?, + ); + let named_key_addr = + NamedKeyAddr::new_from_string(entity_addr, name.clone()).map_err(|_| Error::PutKey)?; + let key = Key::NamedKey(named_key_addr); + // write to both tracking copy and in-mem named keys cache + self.tracking_copy() + .borrow_mut() + .write(key, named_key_value); + match self.named_keys_mut().insert(name, key) { + Some(_) => Ok(()), + None => Err(Error::PutKey), + } + } + + fn remove_key(&mut self, name: &str) -> Result<(), Error> { + self.named_keys_mut().remove(name); + let entity = self.addressable_entity(); + let addressable_entity_hash = AddressableEntityHash::new(self.address().value()); + let entity_addr = entity.entity_addr(addressable_entity_hash); + let named_key_addr = NamedKeyAddr::new_from_string(entity_addr, name.to_string()) + .map_err(|_| Error::RemoveKey)?; + let key = Key::NamedKey(named_key_addr); + let tc = self.tracking_copy(); + if let Some(StoredValue::NamedKey(_)) = + tc.borrow_mut().read(&key).map_err(|_| Error::RemoveKey)? + { + tc.borrow_mut().prune(key); + } + Ok(()) + } + + fn get_phase(&self) -> Phase { + self.phase() + } + + fn get_caller(&self) -> AccountHash { + self.address() + } + + fn refund_handling(&self) -> RefundHandling { + *self.config().refund_handling() + } + + fn fee_handling(&self) -> FeeHandling { + *self.config().fee_handling() + } + + fn administrative_accounts(&self) -> BTreeSet { + self.transfer_config().administrative_accounts() + } +} + +impl StorageProvider for RuntimeNative +where + S: StateReader, +{ + fn write_balance(&mut self, purse_uref: URef, amount: U512) -> Result<(), Error> { + let cl_value = CLValue::from_t(amount).map_err(|_| Error::Storage)?; + self.tracking_copy().borrow_mut().write( + Key::Balance(purse_uref.addr()), + StoredValue::CLValue(cl_value), + ); + Ok(()) + } +} + +impl HandlePayment for RuntimeNative where + S: StateReader +{ +} diff --git a/storage/src/system/handle_payment/internal.rs b/storage/src/system/handle_payment/internal.rs index 7cab48fc71..6ca8d62dc6 100644 --- a/storage/src/system/handle_payment/internal.rs +++ b/storage/src/system/handle_payment/internal.rs @@ -1,14 +1,12 @@ +use casper_types::{ + system::handle_payment::{Error, PAYMENT_PURSE_KEY, REFUND_PURSE_KEY}, + FeeHandling, HoldsEpoch, Key, Phase, PublicKey, RefundHandling, URef, U512, +}; use num::{CheckedMul, One}; use num_rational::Ratio; use num_traits::Zero; use tracing::error; -use casper_types::{ - account::AccountHash, - system::handle_payment::{Error, ACCUMULATION_PURSE_KEY, PAYMENT_PURSE_KEY, REFUND_PURSE_KEY}, - FeeHandling, Key, Phase, PublicKey, RefundHandling, URef, U512, -}; - use super::{ mint_provider::MintProvider, runtime_provider::RuntimeProvider, storage_provider::StorageProvider, @@ -45,224 +43,258 @@ pub fn get_refund_purse( } } -/// Returns tuple where 1st element is the refund, and 2nd element is the fee. +/// Returns tuple where 1st element is the portion of unspent payment (if any), and the 2nd element +/// is the fee (if any). /// /// # Note /// /// Any dust amounts are added to the fee. -fn calculate_refund_and_fee( - gas_spent: U512, - payment_purse_balance: U512, - refund_handling: &RefundHandling, +fn calculate_overpayment_and_fee( + limit: U512, + gas_price: u8, + cost: U512, + consumed: U512, + available_balance: U512, + refund_handling: RefundHandling, ) -> Result<(U512, U512), Error> { - let unspent = payment_purse_balance - .checked_sub(gas_spent) - .ok_or(Error::ArithmeticOverflow)?; - + /* + cost is limit * price, unused = limit - consumed + base refund is unused * price + refund rate is a percentage ranging from 0% to 100% + actual refund = base refund * refund rate + i.e. if rate == 100%, actual refund == base refund + if rate = 0%, actual refund = 0 (and we can skip refund processing) + EXAMPLE 1 + limit = 500, consumed = 450, price = 2, refund rate = 100% + cost = limit * price == 1000 + unused = limit - consumed == 50 + base refund = unused * price == 100 + actual refund = base refund * refund rate == 100 + + EXAMPLE 2 + limit = 5000, consumed = 0, price = 5, refund rate = 50% + cost = limit * price == 25000 + unused = limit - consumed == 5000 + base refund = unused * price == 25000 + actual refund = base refund * refund rate == 12500 + + Complicating factors: + if the source purse does not have enough to cover the cost, their available balance is taken + and there is no refund + if the refund rate is 0%, there is no refund (although it would be bizarre for a network to + run with RefundHandling turned on but with a 0% rate, they are technically independent + settings and thus the logic must account for the possibility) + cost might be higher than limit * price if additional costs have been incurred. + as the refund calculation is based on paid for but unused gas, such additional costs + are not subject to refund. This is handled by this logic correctly, but tests over logic + that incurs any additional costs need to use actual discrete variables for each value + and not assume limit * price == cost + */ + if available_balance < cost { + return Ok((U512::zero(), available_balance)); + } + if refund_handling.skip_refund() { + return Ok((U512::zero(), cost)); + } + let unspent = limit.saturating_sub(consumed); + if unspent == U512::zero() { + return Ok((U512::zero(), cost)); + } + let base_refund = unspent * gas_price; let refund_ratio = match refund_handling { RefundHandling::Refund { refund_ratio } | RefundHandling::Burn { refund_ratio } => { debug_assert!( - refund_ratio <= &Ratio::one(), + refund_ratio <= Ratio::one(), "refund ratio should be a proper fraction" ); - let (numer, denom) = (*refund_ratio).into(); + let (numer, denom) = refund_ratio.into(); Ratio::new_raw(U512::from(numer), U512::from(denom)) } - RefundHandling::None => Ratio::zero(), + RefundHandling::NoRefund => Ratio::zero(), }; - let refund = Ratio::from(unspent) + let adjusted_refund = Ratio::from(base_refund) .checked_mul(&refund_ratio) .ok_or(Error::ArithmeticOverflow)? .to_integer(); - let fee = payment_purse_balance - .checked_sub(refund) + let fee = cost + .checked_sub(adjusted_refund) .ok_or(Error::ArithmeticOverflow)?; - Ok((refund, fee)) + Ok((adjusted_refund, fee)) } -/// Transfers funds from the payment purse to the proposer, accumulation purse or burns the amount -/// depending on a [`FeeHandling`] configuration option. This function can also transfer funds to a -/// refund purse, depending on how much was spent on the computation, or burns the refund. This code -/// maintains the invariant that the balance of the payment purse is zero at the beginning and end -/// of each deploy and that the refund purse is unset at the beginning and end of each deploy. +/// This function handles payment post-processing to pay out fees and refunds. +/// +/// The behavior of this function is very load bearing and complex, based on every possible +/// combination of [`FeeHandling`] and [`RefundHandling`] handling variants. +/// +/// NOTE: If a network is configured for both NoFee and NoRefund, this method will error if called. +#[allow(clippy::too_many_arguments)] pub fn finalize_payment( provider: &mut P, - gas_spent: U512, - account: AccountHash, - target: URef, + limit: U512, + gas_price: u8, + cost: U512, + consumed: U512, + source_purse: URef, + target_purse: URef, + holds_epoch: HoldsEpoch, ) -> Result<(), Error> { + let refund_handling = provider.refund_handling(); + let fee_handling = provider.fee_handling(); + if fee_handling.skip_fee_handling() && refund_handling.skip_refund() { + // this method should not even be called if NoFee && NoRefund are set, + // as there is nothing to finalize + return Err(Error::IncompatiblePaymentSettings); + } + let caller = provider.get_caller(); if caller != PublicKey::System.to_account_hash() { return Err(Error::SystemFunctionCalledByUserAccount); } - let payment_purse = get_payment_purse(provider)?; - let mut payment_amount = match provider.balance(payment_purse)? { + let source_available_balance = match provider.available_balance(source_purse, holds_epoch)? { Some(balance) => balance, None => return Err(Error::PaymentPurseBalanceNotFound), }; - if payment_amount < gas_spent { - return Err(Error::InsufficientPaymentForAmountSpent); - } - - let (refund, fee) = - calculate_refund_and_fee(gas_spent, payment_amount, provider.refund_handling())?; - - debug_assert_eq!(fee + refund, payment_amount); - - // Give or burn the refund. - match provider.refund_handling() { - RefundHandling::Refund { .. } => { - let refund_purse = get_refund_purse(provider)?; - - if let Some(refund_purse) = refund_purse { - if refund_purse.remove_access_rights() == payment_purse.remove_access_rights() { - // Make sure we're not refunding into a payment purse to invalidate payment - // code postconditions. - return Err(Error::RefundPurseIsPaymentPurse); - } - } - - provider.remove_key(REFUND_PURSE_KEY)?; //unset refund purse after reading it - - if !refund.is_zero() { - match refund_purse { - Some(refund_purse) => { - // In case of failure to transfer to refund purse we fall back on the - // account's main purse - match provider.transfer_purse_to_purse(payment_purse, refund_purse, refund) - { - Ok(()) => {} - Err(error) => { - error!( - %error, - %refund, - %account, - "unable to transfer refund to a refund purse; refunding to account" - ); - refund_to_account::

(provider, payment_purse, account, refund)?; - } - } + let (refund, fee) = calculate_overpayment_and_fee( + limit, + gas_price, + cost, + consumed, + source_available_balance, + refund_handling, + )?; + + if !refund.is_zero() { + match refund_handling { + RefundHandling::Refund { .. } => { + let maybe_refund_purse = get_refund_purse(provider)?; + if let Some(refund_purse) = maybe_refund_purse { + // refund purse cannot also be source purse + if refund_purse.remove_access_rights() == source_purse.remove_access_rights() { + return Err(Error::RefundPurseIsPaymentPurse); } - None => { - refund_to_account::

(provider, payment_purse, account, refund)?; + //unset refund purse after reading it + provider.remove_key(REFUND_PURSE_KEY)?; + if let Err(error) = + provider.transfer_purse_to_purse(source_purse, refund_purse, refund) + { + error!( + %error, + %refund, + %source_purse, + %refund_purse, + "unable to transfer refund to a refund purse" + ); } } } - } - - RefundHandling::Burn { .. } if !refund.is_zero() => { - // Fee-handling is set to `Burn`. Deduct the refund from the payment purse and - // reduce the total supply (i.e. burn the refund). - payment_amount = payment_amount - .checked_sub(refund) - .ok_or(Error::ArithmeticOverflow)?; - - provider.write_balance(payment_purse, payment_amount)?; - provider.reduce_total_supply(refund)?; - } - - RefundHandling::Burn { .. } => { - // No refund to burn - } - - RefundHandling::None => { - // noop + RefundHandling::Burn { .. } => { + burn(provider, source_purse, Some(refund))?; + } + RefundHandling::NoRefund => { + // this must be due to either programmer error or invalid chainspec settings + return Err(Error::IncompatiblePaymentSettings); + } } } // Pay or burn the fee. - match provider.fee_handling() { + match fee_handling { FeeHandling::PayToProposer | FeeHandling::Accumulate => { - // target purse is already resolved based on fee-handling config which is either a - // proposer or accumulation purse. - match provider.transfer_purse_to_purse(payment_purse, target, fee) { + match provider.transfer_purse_to_purse(source_purse, target_purse, fee) { Ok(()) => {} Err(error) => { - error!(%error, %fee, %target, "unable to transfer fee"); + error!(%error, %fee, %target_purse, "unable to transfer fee"); return Err(Error::FailedTransferToRewardsPurse); } } } FeeHandling::Burn => { - debug_assert_eq!( - target, - URef::default(), - "Caller should pass a defaulted URef if the fees are burned" - ); - // Fee-handling is set to `Burn`. Deduct the fee from the payment purse, leaving it - // empty, and reduce the total supply (i.e. burn the fee). - provider.write_balance(payment_purse, U512::zero())?; - provider.reduce_total_supply(fee)?; + burn(provider, source_purse, Some(refund))?; } - FeeHandling::None => { - // noop + FeeHandling::NoFee => { + if !fee.is_zero() { + // this must be due to either programmer error or invalid chainspec settings + return Err(Error::IncompatiblePaymentSettings); + } } } Ok(()) } -pub fn refund_to_account( - mint_provider: &mut M, - payment_purse: URef, - account: AccountHash, - amount: U512, +pub fn burn( + provider: &mut P, + purse: URef, + amount: Option, ) -> Result<(), Error> { - match mint_provider.transfer_purse_to_account(payment_purse, account, amount) { - Ok(_) => Ok(()), - Err(error) => { - error!(%error, %amount, %account, "unable to process refund from payment purse to account"); - Err(Error::FailedTransferToAccountPurse) - } - } -} - -/// Gets an accumulation purse from the named keys. -fn get_accumulation_purse(provider: &mut R) -> Result { - match provider.get_key(ACCUMULATION_PURSE_KEY) { - Some(Key::URef(purse_uref)) => Ok(purse_uref), - Some(_key) => Err(Error::AccumulationPurseKeyUnexpectedType), - None => Err(Error::AccumulationPurseNotFound), + // get the purse total balance (without holds) + let total_balance = match provider.available_balance(purse, HoldsEpoch::NOT_APPLICABLE)? { + Some(balance) => balance, + None => return Err(Error::PaymentPurseBalanceNotFound), + }; + let burn_amount = amount.unwrap_or(total_balance); + if burn_amount.is_zero() { + // nothing to burn == noop + return Ok(()); } + // Reduce the source purse and total supply by the refund amount + let adjusted_balance = total_balance + .checked_sub(burn_amount) + .ok_or(Error::ArithmeticOverflow)?; + provider.write_balance(purse, adjusted_balance)?; + provider.reduce_total_supply(burn_amount)?; + Ok(()) } /// This function distributes the fees according to the fee handling config. -pub fn distribute_accumulated_fees

(provider: &mut P) -> Result<(), Error> +/// +/// NOTE: If a network is not configured for fee accumulation, this method will error if called. +pub fn distribute_accumulated_fees

( + provider: &mut P, + source_uref: URef, + amount: Option, +) -> Result<(), Error> where P: RuntimeProvider + MintProvider, { - if provider.get_caller() != PublicKey::System.to_account_hash() { - return Err(Error::SystemFunctionCalledByUserAccount); + let fee_handling = provider.fee_handling(); + if !fee_handling.is_accumulate() { + return Err(Error::IncompatiblePaymentSettings); } - // Distribute accumulation purse balance into all administrators - match provider.fee_handling() { - FeeHandling::PayToProposer | FeeHandling::Burn | FeeHandling::None => return Ok(()), - FeeHandling::Accumulate => {} + if provider.get_caller() != PublicKey::System.to_account_hash() { + return Err(Error::SystemFunctionCalledByUserAccount); } - let administrative_accounts = provider.administrative_accounts().clone(); - let accumulation_purse = get_accumulation_purse(provider)?; - let accumulated_balance = provider.balance(accumulation_purse)?.unwrap_or_default(); + let administrative_accounts = provider.administrative_accounts(); let reward_recipients = U512::from(administrative_accounts.len()); - if let Some(reward_amount) = accumulated_balance.checked_div(reward_recipients) { - if reward_amount.is_zero() { - // There is zero tokens to be paid out which means we can exit early. - return Ok(()); - } + let distribute_amount = match amount { + Some(amount) => amount, + None => provider + .available_balance(source_uref, HoldsEpoch::NOT_APPLICABLE)? + .unwrap_or_default(), + }; + if distribute_amount.is_zero() { + return Ok(()); + } + + let portion = distribute_amount + .checked_div(reward_recipients) + .unwrap_or_else(U512::zero); + + if !portion.is_zero() { for target in administrative_accounts { - provider.transfer_purse_to_account(accumulation_purse, target, reward_amount)?; + provider.transfer_purse_to_account(source_uref, target, portion)?; } } - // Any dust amount left in the accumulation purse for the next round. - Ok(()) } @@ -270,75 +302,181 @@ where mod tests { use super::*; + // both burn and refund use the same basic calculation for + // overpayment / unspent vs fee...the only difference is + // what is done with the overage _after_ the calculation + // refund returns it to payer, while burn destroys it + #[test] - fn should_move_dust_to_reward() { - let refund_ratio = Ratio::new_raw(1, 3); - let refund = RefundHandling::Refund { refund_ratio }; - test_refund_handling(&refund); + fn should_burn_expected_amount() { + let handling = RefundHandling::Burn { + refund_ratio: Ratio::new_raw(1, 1), + }; + test_handle_payment(handling); + } - let burn = RefundHandling::Burn { refund_ratio }; - test_refund_handling(&burn); + #[test] + fn should_refund_expected_amount() { + let handling = RefundHandling::Refund { + refund_ratio: Ratio::new_raw(1, 1), + }; + test_handle_payment(handling); } - fn test_refund_handling(refund_handling: &RefundHandling) { - let purse_bal = U512::from(10u64); - let gas = U512::from(3u64); - let (a, b) = calculate_refund_and_fee(gas, purse_bal, refund_handling).unwrap(); - assert_eq!(a, U512::from(2u64)); - // (10 - 3) * 1/3 ~ 2.33 (.33 is dust) - assert_eq!(b, U512::from(8u64)); - // 10 - 2 = 8 + #[test] + fn should_handle_straight_percentages() { + let limit = U512::from(100u64); + let gas_price = 1; + let cost = limit; + let consumed = U512::from(50u64); + let available = U512::from(1000u64); + let denom = 100; + + for numer in 0..=denom { + let refund_ratio = Ratio::new_raw(numer, denom); + let handling = RefundHandling::Refund { refund_ratio }; + let (overpay, fee) = calculate_overpayment_and_fee( + limit, gas_price, cost, consumed, available, handling, + ) + .unwrap(); + + let unspent = limit.saturating_sub(consumed).as_u64(); + let expected = Ratio::from(unspent) + .checked_mul(&refund_ratio) + .ok_or(Error::ArithmeticOverflow) + .expect("should math") + .to_integer(); + assert_eq!(expected, overpay.as_u64(), "overpay"); + let expected_fee = limit.as_u64() - expected; + assert_eq!(expected_fee, fee.as_u64(), "fee"); + } + } + + fn test_handle_payment(refund_handling: RefundHandling) { + let limit = U512::from(6u64); + let gas_price = 1; + let cost = limit; + let consumed = U512::from(3u64); + let available = U512::from(10u64); + let (overpay, fee) = calculate_overpayment_and_fee( + limit, + gas_price, + cost, + consumed, + available, + refund_handling, + ) + .unwrap(); + + let unspent = limit.saturating_sub(consumed); + let expected = unspent; + assert_eq!(expected, overpay, "{:?}", refund_handling); + let expected_fee = consumed; + assert_eq!(expected_fee, fee, "fee"); } #[test] - fn should_account_refund_for_dust() { - let purse_bal = U512::from(9973u64); - let gas = U512::from(9161u64); + fn should_roll_over_dust() { + let limit = U512::from(6u64); + let gas_price = 1; + let cost = limit; + let consumed = U512::from(3u64); + let available = U512::from(10u64); for percentage in 0..=100 { - let refund_ratio = Ratio::new_raw(percentage, 100); - let refund = RefundHandling::Refund { refund_ratio }; + let handling = RefundHandling::Refund { + refund_ratio: Ratio::new_raw(percentage, 100), + }; - let (a, b) = calculate_refund_and_fee(gas, purse_bal, &refund).unwrap(); + let (overpay, fee) = calculate_overpayment_and_fee( + limit, gas_price, cost, consumed, available, handling, + ) + .expect("should have overpay and fee"); - let a = Ratio::from(a); - let b = Ratio::from(b); + let a = Ratio::from(overpay); + let b = Ratio::from(fee); - assert_eq!(a + b, Ratio::from(purse_bal)); + assert_eq!(a + b, Ratio::from(cost), "{}", percentage); } } -} - -#[cfg(test)] -mod proptests { - use proptest::prelude::*; - - use super::*; - const DENOM_MAX: u64 = 1000; - const BALANCE_MAX: u64 = 100_000_000; - - prop_compose! { - fn proper_fraction(max: u64) - (numerator in 0..=max) - (numerator in Just(numerator), denom in numerator..=max) -> Ratio { - Ratio::new(numerator, denom) - } + #[test] + fn should_take_all_of_insufficient_balance() { + let limit = U512::from(6u64); + let gas_price = 1; + let cost = limit; + let consumed = U512::from(3u64); + let available = U512::from(5u64); + + let (overpay, fee) = calculate_overpayment_and_fee( + limit, + gas_price, + cost, + consumed, + available, + RefundHandling::Refund { + refund_ratio: Ratio::new_raw(1, 1), + }, + ) + .unwrap(); + + assert_eq!(U512::zero(), overpay, "overpay"); + let expected = available; + assert_eq!(expected, fee, "fee"); } - prop_compose! { - fn balance_and_gas(max_balance: u64)(balance in 100..=max_balance)(balance in Just(balance), gas in 1..=balance) -> (U512, U512) { - (U512::from(balance), U512::from(gas)) - } + #[test] + fn should_handle_non_1_gas_price() { + let limit = U512::from(6u64); + let gas_price = 2; + let cost = limit * gas_price; + let consumed = U512::from(3u64); + let available = U512::from(12u64); + + let (overpay, fee) = calculate_overpayment_and_fee( + limit, + gas_price, + cost, + consumed, + available, + RefundHandling::Refund { + refund_ratio: Ratio::new_raw(1, 1), + }, + ) + .unwrap(); + + let unspent = limit.saturating_sub(consumed); + let expected = unspent * gas_price; + assert_eq!(expected, overpay, "overpay"); + let expected_fee = consumed * gas_price; + assert_eq!(expected_fee, fee, "fee"); } - proptest! { - #[test] - fn refund_and_fee_equals_balance(refund_ratio in proper_fraction(DENOM_MAX), (balance, gas) in balance_and_gas(BALANCE_MAX)) { - let refund = RefundHandling::Refund { refund_ratio }; - - let (refund, fee) = calculate_refund_and_fee(gas, balance, &refund).unwrap(); - prop_assert_eq!(refund + fee, balance); - } + #[test] + fn should_handle_extra_cost() { + let limit = U512::from(6u64); + let gas_price = 2; + let extra_cost = U512::from(1u64); + let cost = limit * gas_price + extra_cost; + let consumed = U512::from(3u64); + let available = U512::from(21u64); + + let (overpay, fee) = calculate_overpayment_and_fee( + limit, + gas_price, + cost, + consumed, + available, + RefundHandling::Refund { + refund_ratio: Ratio::new_raw(1, 1), + }, + ) + .unwrap(); + + let unspent = limit.saturating_sub(consumed); + let expected = unspent * gas_price; + assert_eq!(expected, overpay, "overpay"); + let expected_fee = consumed * gas_price + extra_cost; + assert_eq!(expected_fee, fee, "fee"); } } diff --git a/storage/src/system/handle_payment/mint_provider.rs b/storage/src/system/handle_payment/mint_provider.rs index bcc13e83d6..f5f81faf0f 100644 --- a/storage/src/system/handle_payment/mint_provider.rs +++ b/storage/src/system/handle_payment/mint_provider.rs @@ -1,10 +1,13 @@ use casper_types::{ - account::AccountHash, system::handle_payment::Error, TransferredTo, URef, U512, + account::AccountHash, system::handle_payment::Error, HoldsEpoch, TransferredTo, URef, U512, }; /// Provides an access to mint. pub trait MintProvider { /// Transfer `amount` from `source` purse to a `target` account. + /// Note: the source should always be a system purse of some kind, + /// such as the payment purse or an accumulator purse. + /// The target should be the recipient of a refund or a reward fn transfer_purse_to_account( &mut self, source: URef, @@ -13,6 +16,9 @@ pub trait MintProvider { ) -> Result; /// Transfer `amount` from `source` purse to a `target` purse. + /// Note: the source should always be a system purse of some kind, + /// such as the payment purse or an accumulator purse. + /// The target should be the recipient of a refund or a reward fn transfer_purse_to_purse( &mut self, source: URef, @@ -21,7 +27,11 @@ pub trait MintProvider { ) -> Result<(), Error>; /// Checks balance of a `purse`. Returns `None` if given purse does not exist. - fn balance(&mut self, purse: URef) -> Result, Error>; + fn available_balance( + &mut self, + purse: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error>; /// Reduce total supply by `amount`. fn reduce_total_supply(&mut self, amount: U512) -> Result<(), Error>; diff --git a/storage/src/system/handle_payment/runtime_provider.rs b/storage/src/system/handle_payment/runtime_provider.rs index 82d3332444..b504605f13 100644 --- a/storage/src/system/handle_payment/runtime_provider.rs +++ b/storage/src/system/handle_payment/runtime_provider.rs @@ -1,8 +1,7 @@ use std::collections::BTreeSet; use casper_types::{ - account::AccountHash, system::handle_payment::Error, BlockTime, FeeHandling, Key, Phase, - RefundHandling, + account::AccountHash, system::handle_payment::Error, FeeHandling, Key, Phase, RefundHandling, }; /// Provider of runtime host functionality. @@ -19,18 +18,15 @@ pub trait RuntimeProvider { /// Get current execution phase. fn get_phase(&self) -> Phase; - /// Get current block time. - fn get_block_time(&self) -> BlockTime; - /// Get caller. fn get_caller(&self) -> AccountHash; /// Get refund handling. - fn refund_handling(&self) -> &RefundHandling; + fn refund_handling(&self) -> RefundHandling; /// Returns fee handling value. fn fee_handling(&self) -> FeeHandling; /// Returns list of administrative accounts. - fn administrative_accounts(&self) -> &BTreeSet; + fn administrative_accounts(&self) -> BTreeSet; } diff --git a/storage/src/system/mint.rs b/storage/src/system/mint.rs index 71c7ff331f..5acfc83798 100644 --- a/storage/src/system/mint.rs +++ b/storage/src/system/mint.rs @@ -12,7 +12,7 @@ use casper_types::{ mint::{Error, ROUND_SEIGNIORAGE_RATE_KEY, TOTAL_SUPPLY_KEY}, Caller, }, - Key, PublicKey, SystemEntityRegistry, URef, U512, + HoldsEpoch, Key, PublicKey, SystemEntityRegistry, URef, U512, }; use crate::system::mint::{ @@ -86,8 +86,8 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { } /// Read balance of given `purse`. - fn balance(&mut self, purse: URef) -> Result, Error> { - match self.read_balance(purse)? { + fn balance(&mut self, purse: URef, hold_epoch: HoldsEpoch) -> Result, Error> { + match self.available_balance(purse, hold_epoch)? { some @ Some(_) => Ok(some), None => Err(Error::PurseNotFound), } @@ -101,6 +101,7 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { target: URef, amount: U512, id: Option, + holds_epoch: HoldsEpoch, ) -> Result<(), Error> { if !self.allow_unrestricted_transfers() { let registry = match self.get_system_entity_registry() { @@ -109,7 +110,7 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { }; let immediate_caller = self.get_immediate_caller(); match immediate_caller { - Some(Caller::AddressableEntity { + Some(Caller::Entity { entity_hash: contract_hash, .. }) if registry.has_contract_hash(&contract_hash) => { @@ -117,20 +118,20 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { // transfer) } - Some(Caller::Session { account_hash: _ }) + Some(Caller::Initiator { account_hash: _ }) if self.is_called_from_standard_payment() => { // Standard payment acts as a session without separate stack frame and calls // into mint's transfer. } - Some(Caller::Session { account_hash }) + Some(Caller::Initiator { account_hash }) if account_hash == PublicKey::System.to_account_hash() => { // System calls a session code. } - Some(Caller::Session { account_hash }) => { + Some(Caller::Initiator { account_hash }) => { // For example: a session using transfer host functions, or calling the mint's // entrypoint directly @@ -179,7 +180,7 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { } } - Some(Caller::AddressableEntity { + Some(Caller::Entity { package_hash: _, entity_hash: _, }) => { @@ -210,14 +211,17 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { // a deposit of token. Generally, deposit of a desirable resource is permissive. return Err(Error::InvalidAccessRights); } - let source_balance: U512 = match self.read_balance(source)? { + let source_balance: U512 = match self.available_balance(source, holds_epoch)? { Some(source_balance) => source_balance, None => return Err(Error::SourceNotFound), }; if amount > source_balance { return Err(Error::InsufficientFunds); } - if self.read_balance(target)?.is_none() { + if self + .available_balance(target, HoldsEpoch::NOT_APPLICABLE)? + .is_none() + { return Err(Error::DestNotFound); } if self.get_caller() != PublicKey::System.to_account_hash() @@ -275,7 +279,10 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { // treat as noop return Ok(()); } - if self.read_balance(existing_purse)?.is_none() { + if self + .available_balance(existing_purse, HoldsEpoch::NOT_APPLICABLE)? + .is_none() + { return Err(Error::PurseNotFound); } self.add_balance(existing_purse, amount)?; diff --git a/storage/src/system/mint/mint_native.rs b/storage/src/system/mint/mint_native.rs index 85b648b3c3..4286c10ad9 100644 --- a/storage/src/system/mint/mint_native.rs +++ b/storage/src/system/mint/mint_native.rs @@ -16,8 +16,8 @@ use casper_types::{ account::AccountHash, bytesrepr::{FromBytes, ToBytes}, system::{mint::Error, Caller}, - AccessRights, AddressableEntity, CLTyped, CLValue, DeployHash, Digest, Key, Phase, PublicKey, - StoredValue, SystemEntityRegistry, TransactionHash, Transfer, TransferAddr, URef, U512, + AccessRights, AddressableEntity, CLTyped, CLValue, Gas, HoldsEpoch, InitiatorAddr, Key, Phase, + PublicKey, StoredValue, SystemEntityRegistry, Transfer, TransferV2, URef, U512, }; impl RuntimeProvider for RuntimeNative @@ -29,7 +29,7 @@ where } fn get_immediate_caller(&self) -> Option { - let caller = Caller::Session { + let caller = Caller::Initiator { account_hash: PublicKey::System.to_account_hash(), }; Some(caller) @@ -44,8 +44,8 @@ where .borrow_mut() .get_system_entity_registry() .map_err(|tce| { - error!(%tce, "unable to obtain system contract registry during transfer"); - ProviderError::SystemContractRegistry + error!(%tce, "unable to obtain system entity registry during transfer"); + ProviderError::SystemEntityRegistry }) } @@ -169,11 +169,15 @@ where Ok(()) } - fn read_balance(&mut self, uref: URef) -> Result, Error> { + fn available_balance( + &mut self, + uref: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error> { match self .tracking_copy() .borrow_mut() - .get_purse_balance(Key::Balance(uref.addr())) + .get_available_balance(Key::Balance(uref.addr()), holds_epoch) { Ok(motes) => Ok(Some(motes.value())), Err(_) => Err(Error::Storage), @@ -213,34 +217,20 @@ where if self.phase() != Phase::Session { return Ok(()); } - let transfer_addr = TransferAddr::new(self.address_generator().create_address()); - let key = Key::Transfer(transfer_addr); // <-- a new key variant needed to deal w/ versioned transaction hash - //let transaction_hash = self.transaction_hash(); - let transfer = { - // the below line is incorrect; new transaction hash is not currently supported here - // ...the transfer struct needs to be upgraded to TransactionHash - let deploy_hash = match self.id() { - Id::Transaction(transaction) => { - match transaction { - TransactionHash::Deploy(deploy_hash) => *deploy_hash, - TransactionHash::V1(hash) => { - // TODO: this is bogus...update when new transfer record is available - let hash = hash.inner(); - DeployHash::new(*hash) - } - } - } - Id::Seed(seed) => DeployHash::new(Digest::hash(seed)), - }; - let from: AccountHash = self.get_caller(); - let fee: U512 = U512::zero(); - Transfer::new(deploy_hash, from, maybe_to, source, target, amount, fee, id) + let txn_hash = match self.id() { + Id::Transaction(txn_hash) => *txn_hash, + // we don't write transfer records for systemic transfers (step, fees, rewards, etc) + // so return Ok and move on. + Id::Seed(_) => return Ok(()), }; - self.push_transfer(transfer_addr); + let from = InitiatorAddr::AccountHash(self.get_caller()); + let fee = Gas::zero(); // TODO + let transfer = Transfer::V2(TransferV2::new( + txn_hash, from, maybe_to, source, target, amount, fee, id, + )); + + self.push_transfer(transfer); - self.tracking_copy() - .borrow_mut() - .write(key, StoredValue::Transfer(transfer)); Ok(()) } } diff --git a/storage/src/system/mint/runtime_provider.rs b/storage/src/system/mint/runtime_provider.rs index 8ade0171ec..b20b46491b 100644 --- a/storage/src/system/mint/runtime_provider.rs +++ b/storage/src/system/mint/runtime_provider.rs @@ -14,7 +14,7 @@ pub trait RuntimeProvider { fn is_called_from_standard_payment(&self) -> bool; - /// Get system contract registry. + /// Get system entity registry. fn get_system_entity_registry(&self) -> Result; fn read_addressable_entity_by_account_hash( diff --git a/storage/src/system/mint/storage_provider.rs b/storage/src/system/mint/storage_provider.rs index efedb9110f..bee74a7daa 100644 --- a/storage/src/system/mint/storage_provider.rs +++ b/storage/src/system/mint/storage_provider.rs @@ -1,7 +1,7 @@ use casper_types::{ bytesrepr::{FromBytes, ToBytes}, system::mint::Error, - CLTyped, URef, U512, + CLTyped, HoldsEpoch, URef, U512, }; /// Provides functionality of a contract storage. @@ -19,7 +19,11 @@ pub trait StorageProvider { fn add(&mut self, uref: URef, value: T) -> Result<(), Error>; /// Read balance. - fn read_balance(&mut self, uref: URef) -> Result, Error>; + fn available_balance( + &mut self, + uref: URef, + holds_epoch: HoldsEpoch, + ) -> Result, Error>; /// Write balance. fn write_balance(&mut self, uref: URef, balance: U512) -> Result<(), Error>; diff --git a/storage/src/system/protocol_upgrade.rs b/storage/src/system/protocol_upgrade.rs index b5fdc7e04d..c139bf45fd 100644 --- a/storage/src/system/protocol_upgrade.rs +++ b/storage/src/system/protocol_upgrade.rs @@ -11,7 +11,6 @@ use casper_types::{ NamedKeyValue, NamedKeys, Weight, }, bytesrepr::{self, ToBytes}, - package::{EntityVersions, Groups, PackageStatus}, system::{ auction::{ BidAddr, BidKind, ValidatorBid, AUCTION_DELAY_KEY, LOCKED_FUNDS_PERIOD_KEY, @@ -22,9 +21,10 @@ use casper_types::{ SystemEntityType, AUCTION, HANDLE_PAYMENT, MINT, }, AccessRights, AddressableEntity, AddressableEntityHash, ByteCode, ByteCodeAddr, ByteCodeHash, - ByteCodeKind, CLValue, CLValueError, Digest, EntityAddr, EntryPoints, FeeHandling, Key, KeyTag, - Package, PackageHash, Phase, ProtocolUpgradeConfig, ProtocolVersion, PublicKey, StoredValue, - SystemEntityRegistry, URef, U512, + ByteCodeKind, CLValue, CLValueError, Digest, EntityAddr, EntityVersions, EntryPoints, + FeeHandling, Groups, Key, KeyTag, Package, PackageHash, PackageStatus, Phase, + ProtocolUpgradeConfig, ProtocolVersion, PublicKey, StoredValue, SystemEntityRegistry, URef, + U512, }; use crate::{ @@ -57,8 +57,8 @@ pub enum ProtocolUpgradeError { /// (De)serialization error. #[error("Bytesrepr error: {0}")] Bytesrepr(String), - /// Failed to create system contract registry. - #[error("Failed to insert system contract registry")] + /// Failed to create system entity registry. + #[error("Failed to insert system entity registry")] FailedToCreateSystemRegistry, /// Found unexpected variant of a stored value. #[error("Unexpected stored value variant")] @@ -190,8 +190,8 @@ where } } - fn system_contract_registry(&self) -> Result { - debug!("system contract registry"); + fn system_entity_registry(&self) -> Result { + debug!("system entity registry"); let registry = if let Ok(registry) = self.tracking_copy.borrow_mut().get_system_entity_registry() { @@ -224,7 +224,7 @@ where /// Handle system entities. pub fn handle_system_entities(&self) -> Result { debug!("handle system entities"); - let mut registry = self.system_contract_registry()?; + let mut registry = self.system_entity_registry()?; let mint = *registry.get(MINT).ok_or_else(|| { error!("Missing system mint entity hash"); @@ -345,7 +345,7 @@ where .write(entity_key, StoredValue::AddressableEntity(new_entity)); if let Some(named_keys) = maybe_named_keys { - let entity_addr = EntityAddr::new_system_entity_addr(entity_hash.value()); + let entity_addr = EntityAddr::new_system(entity_hash.value()); for (string, key) in named_keys.into_inner().into_iter() { let entry_addr = NamedKeyAddr::new_from_string(entity_addr, string.clone()) @@ -450,7 +450,7 @@ where if let Some(StoredValue::AddressableEntity(system_entity)) = self .tracking_copy .borrow_mut() - .read(&Key::AddressableEntity(EntityAddr::new_system_entity_addr( + .read(&Key::AddressableEntity(EntityAddr::new_system( entity_hash.value(), ))) .map_err(|_| { @@ -571,7 +571,7 @@ where debug!(?fee_handling, "create accumulation purse if required"); match fee_handling { FeeHandling::PayToProposer | FeeHandling::Burn => return Ok(()), - FeeHandling::Accumulate | FeeHandling::None => {} + FeeHandling::Accumulate | FeeHandling::NoFee => {} } let mut address_generator = { let seed_bytes = ( @@ -587,7 +587,7 @@ where let (addressable_entity, maybe_named_keys, _) = self.retrieve_system_entity(*handle_payment_hash, system_contract)?; - let entity_addr = EntityAddr::new_system_entity_addr(handle_payment_hash.value()); + let entity_addr = EntityAddr::new_system(handle_payment_hash.value()); if let Some(named_keys) = maybe_named_keys { for (string, key) in named_keys.into_inner().into_iter() { @@ -658,7 +658,7 @@ where if let Some(new_validator_slots) = self.config.new_validator_slots() { debug!(%new_validator_slots, "handle new validator slots"); // if new total validator slots is provided, update auction contract state - let auction_addr = EntityAddr::new_system_entity_addr(auction.value()); + let auction_addr = EntityAddr::new_system(auction.value()); let auction_named_keys = self .tracking_copy .borrow_mut() @@ -684,7 +684,7 @@ where ) -> Result<(), ProtocolUpgradeError> { if let Some(new_auction_delay) = self.config.new_auction_delay() { debug!(%new_auction_delay, "handle new auction delay"); - let auction_addr = EntityAddr::new_system_entity_addr(auction.value()); + let auction_addr = EntityAddr::new_system(auction.value()); let auction_named_keys = self .tracking_copy @@ -711,7 +711,7 @@ where ) -> Result<(), ProtocolUpgradeError> { if let Some(new_locked_funds_period) = self.config.new_locked_funds_period_millis() { debug!(%new_locked_funds_period,"handle new locked funds period millis"); - let auction_addr = EntityAddr::new_system_entity_addr(auction.value()); + let auction_addr = EntityAddr::new_system(auction.value()); let auction_named_keys = self .tracking_copy @@ -740,7 +740,7 @@ where // based on the previous unbonding delay. if let Some(new_unbonding_delay) = self.config.new_unbonding_delay() { debug!(%new_unbonding_delay,"handle new unbonding delay"); - let auction_addr = EntityAddr::new_system_entity_addr(auction.value()); + let auction_addr = EntityAddr::new_system(auction.value()); let auction_named_keys = self .tracking_copy @@ -772,7 +772,7 @@ where Ratio::new(numer.into(), denom.into()) }; - let mint_addr = EntityAddr::new_system_entity_addr(mint.value()); + let mint_addr = EntityAddr::new_system(mint.value()); let mint_named_keys = self.tracking_copy.borrow_mut().get_named_keys(mint_addr)?; diff --git a/storage/src/system/runtime_native.rs b/storage/src/system/runtime_native.rs index 6de5d8adf1..54995eaa6d 100644 --- a/storage/src/system/runtime_native.rs +++ b/storage/src/system/runtime_native.rs @@ -6,7 +6,7 @@ use crate::{ use casper_types::{ account::AccountHash, addressable_entity::NamedKeys, AddressableEntity, Chainspec, ContextAccessRights, FeeHandling, Key, Phase, ProtocolVersion, PublicKey, RefundHandling, - StoredValue, TransactionHash, TransferAddr, URef, U512, + StoredValue, TransactionHash, Transfer, URef, U512, }; use std::{cell::RefCell, collections::BTreeSet, rc::Rc}; @@ -20,11 +20,12 @@ pub struct Config { compute_rewards: bool, max_delegators_per_validator: u32, minimum_delegation_amount: u64, + balance_hold_interval: u64, } impl Config { #[allow(clippy::too_many_arguments)] - pub fn new( + pub const fn new( transfer_config: TransferConfig, fee_handling: FeeHandling, refund_handling: RefundHandling, @@ -33,6 +34,7 @@ impl Config { compute_rewards: bool, max_delegators_per_validator: u32, minimum_delegation_amount: u64, + balance_hold_interval: u64, ) -> Self { Config { transfer_config, @@ -43,6 +45,7 @@ impl Config { compute_rewards, max_delegators_per_validator, minimum_delegation_amount, + balance_hold_interval, } } @@ -55,6 +58,7 @@ impl Config { let compute_rewards = chainspec.core_config.compute_rewards; let max_delegators_per_validator = chainspec.core_config.max_delegators_per_validator; let minimum_delegation_amount = chainspec.core_config.minimum_delegation_amount; + let balance_hold_interval = chainspec.core_config.balance_hold_interval.millis(); Config::new( transfer_config, fee_handling, @@ -64,6 +68,7 @@ impl Config { compute_rewards, max_delegators_per_validator, minimum_delegation_amount, + balance_hold_interval, ) } @@ -87,7 +92,7 @@ impl Config { self.allow_auction_bids } - pub fn should_compute_rewards(&self) -> bool { + pub fn compute_rewards(&self) -> bool { self.compute_rewards } @@ -99,6 +104,10 @@ impl Config { self.minimum_delegation_amount } + pub fn balance_hold_interval(&self) -> u64 { + self.balance_hold_interval + } + pub fn set_transfer_config(self, transfer_config: TransferConfig) -> Self { Config { transfer_config, @@ -109,6 +118,7 @@ impl Config { allow_auction_bids: self.allow_auction_bids, minimum_delegation_amount: self.minimum_delegation_amount, compute_rewards: self.compute_rewards, + balance_hold_interval: self.balance_hold_interval, } } } @@ -229,7 +239,7 @@ pub struct RuntimeNative { named_keys: NamedKeys, access_rights: ContextAccessRights, remaining_spending_limit: U512, - transfers: Vec, + transfers: Vec, phase: Phase, } @@ -239,8 +249,8 @@ where { #[allow(clippy::too_many_arguments)] pub fn new( - protocol_version: ProtocolVersion, config: Config, + protocol_version: ProtocolVersion, id: Id, tracking_copy: Rc>>, address: AccountHash, @@ -335,10 +345,18 @@ where &self.named_keys } - pub fn access_rights(&self) -> &ContextAccessRights { + pub fn named_keys_mut(&mut self) -> &mut NamedKeys { + &mut self.named_keys + } + + pub fn access_rights(&mut self) -> &ContextAccessRights { &self.access_rights } + pub fn access_rights_mut(&mut self) -> &mut ContextAccessRights { + &mut self.access_rights + } + pub fn extend_access_rights(&mut self, urefs: &[URef]) { self.access_rights.extend(urefs) } @@ -351,25 +369,18 @@ where self.remaining_spending_limit = remaining; } - pub fn transfers(&self) -> &Vec { + pub fn transfers(&self) -> &Vec { &self.transfers } - pub fn push_transfer(&mut self, transfer_addr: TransferAddr) { - self.transfers.push(transfer_addr); + pub fn push_transfer(&mut self, transfer: Transfer) { + self.transfers.push(transfer); } pub fn id(&self) -> &Id { &self.id } - pub fn maybe_transaction_hash(&self) -> Option { - match self.id { - Id::Transaction(ret) => Some(ret), - Id::Seed(_) => None, - } - } - pub fn phase(&self) -> Phase { self.phase } @@ -386,7 +397,7 @@ where self.config.compute_rewards } - pub fn into_transfers(self) -> Vec { + pub fn into_transfers(self) -> Vec { self.transfers } } diff --git a/storage/src/system/transfer.rs b/storage/src/system/transfer.rs index c23a40c940..f54db564fd 100644 --- a/storage/src/system/transfer.rs +++ b/storage/src/system/transfer.rs @@ -6,8 +6,8 @@ use casper_types::{ addressable_entity::NamedKeys, bytesrepr::FromBytes, system::{mint, mint::Error as MintError}, - AccessRights, AddressableEntity, CLType, CLTyped, CLValue, CLValueError, Key, ProtocolVersion, - RuntimeArgs, StoredValue, StoredValueTypeMismatch, URef, U512, + AccessRights, AddressableEntity, CLType, CLTyped, CLValue, CLValueError, HoldsEpoch, Key, + ProtocolVersion, RuntimeArgs, StoredValue, StoredValueTypeMismatch, URef, U512, }; use crate::{ @@ -172,15 +172,15 @@ impl TransferArgs { self.target } - /// Returns `arg_id` field. - pub fn arg_id(&self) -> Option { - self.arg_id - } - /// Returns `amount` field. pub fn amount(&self) -> U512 { self.amount } + + /// Returns `arg_id` field. + pub fn arg_id(&self) -> Option { + self.arg_id + } } impl TryFrom for RuntimeArgs { @@ -230,7 +230,10 @@ impl TransferRuntimeArgsBuilder { Ok(key) => key, Err(_) => return false, }; - tracking_copy.borrow_mut().get_purse_balance(key).is_ok() + tracking_copy + .borrow_mut() + .get_available_balance(key, HoldsEpoch::NOT_APPLICABLE) + .is_ok() } /// Resolves the source purse of the transfer. @@ -398,11 +401,11 @@ impl TransferRuntimeArgsBuilder { } fn resolve_id(&self) -> Result, TransferError> { - let id_value = self - .inner - .get(mint::ARG_ID) - .ok_or_else(|| TransferError::MissingArgument)?; - let id: Option = self.map_cl_value(id_value)?; + let id: Option = if let Some(id_value) = self.inner.get(mint::ARG_ID) { + self.map_cl_value(id_value)? + } else { + None + }; Ok(id) } @@ -417,7 +420,7 @@ impl TransferRuntimeArgsBuilder { where R: StateReader, { - let (to, target_uref) = match self + let (to, target) = match self .resolve_transfer_target_mode(protocol_version, Rc::clone(&tracking_copy))? { NewTransferTargetMode::ExistingAccount { @@ -436,23 +439,23 @@ impl TransferRuntimeArgsBuilder { } }; - let source_uref = + let source = self.resolve_source_uref(from, entity_named_keys, Rc::clone(&tracking_copy))?; - if source_uref.addr() == target_uref.addr() { + if source.addr() == target.addr() { return Err(TransferError::InvalidPurse); } let amount = self.resolve_amount()?; - let id = self.resolve_id()?; + let arg_id = self.resolve_id()?; Ok(TransferArgs { to, - source: source_uref, - target: target_uref, + source, + target, amount, - arg_id: id, + arg_id, }) } diff --git a/storage/src/tracking_copy/byte_size.rs b/storage/src/tracking_copy/byte_size.rs index ce45d6cebc..417defdd05 100644 --- a/storage/src/tracking_copy/byte_size.rs +++ b/storage/src/tracking_copy/byte_size.rs @@ -35,7 +35,7 @@ impl ByteSize for StoredValue { } StoredValue::Package(package) => package.serialized_length(), StoredValue::DeployInfo(deploy_info) => deploy_info.serialized_length(), - StoredValue::Transfer(transfer) => transfer.serialized_length(), + StoredValue::LegacyTransfer(transfer_v1) => transfer_v1.serialized_length(), StoredValue::EraInfo(era_info) => era_info.serialized_length(), StoredValue::Bid(bid) => bid.serialized_length(), StoredValue::BidKind(bid_kind) => bid_kind.serialized_length(), diff --git a/storage/src/tracking_copy/error.rs b/storage/src/tracking_copy/error.rs index 7cc3c16445..818bf84ac6 100644 --- a/storage/src/tracking_copy/error.rs +++ b/storage/src/tracking_copy/error.rs @@ -2,8 +2,7 @@ use thiserror::Error; use casper_types::{ addressable_entity::{AddKeyFailure, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure}, - bytesrepr, system, AccessRights, ApiError, CLType, CLValueError, Key, StoredValueTypeMismatch, - URef, + bytesrepr, system, ApiError, CLType, CLValueError, Key, StoredValueTypeMismatch, }; /// Possible tracking copy errors. @@ -28,21 +27,6 @@ pub enum Error { /// Type mismatch error. #[error("{}", _0)] TypeMismatch(StoredValueTypeMismatch), - /// Invalid access. - #[error("Invalid access rights: {}", required)] - InvalidAccess { - /// Required access rights of the operation. - required: AccessRights, - }, - /// Forged reference error. - #[error("Forged reference: {}", _0)] - ForgedReference(URef), - /// Unable to find a [`URef`]. - #[error("URef not found: {}", _0)] - URefNotFound(URef), - /// Execution exceeded the gas limit. - #[error("Out of gas error")] - GasLimit, /// ApiError. #[error("{}", _0)] Api(ApiError), @@ -91,6 +75,9 @@ pub enum Error { /// Not authorized. #[error("Authorization error")] Authorization, + /// The value wasn't found. + #[error("Value not found")] + ValueNotFound(String), } impl Error { diff --git a/storage/src/tracking_copy/ext.rs b/storage/src/tracking_copy/ext.rs index 7cc5b4e167..801e8c8f33 100644 --- a/storage/src/tracking_copy/ext.rs +++ b/storage/src/tracking_copy/ext.rs @@ -1,10 +1,17 @@ -use std::{collections::BTreeSet, convert::TryInto}; +use std::{ + collections::{btree_map::Entry, BTreeMap, BTreeSet}, + convert::TryInto, +}; -use crate::global_state::{error::Error as GlobalStateError, state::StateReader}; +use crate::{ + data_access_layer::balance::BalanceHoldsWithProof, + global_state::{error::Error as GlobalStateError, state::StateReader}, +}; use casper_types::{ - account::AccountHash, addressable_entity::NamedKeys, global_state::TrieMerkleProof, ByteCode, - ByteCodeAddr, ByteCodeHash, CLValue, ChecksumRegistry, EntityAddr, Key, KeyTag, Motes, Package, - PackageHash, StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, URef, + account::AccountHash, addressable_entity::NamedKeys, global_state::TrieMerkleProof, + system::mint::BalanceHoldAddrTag, BlockTime, ByteCode, ByteCodeAddr, ByteCodeHash, CLValue, + ChecksumRegistry, EntityAddr, HoldsEpoch, Key, KeyTag, Motes, Package, PackageHash, + StoredValue, StoredValueTypeMismatch, SystemEntityRegistry, URef, URefAddr, U512, }; use crate::tracking_copy::{TrackingCopy, TrackingCopyError}; @@ -20,8 +27,13 @@ pub trait TrackingCopyExt { /// Gets the purse balance key for a given purse. fn get_purse_balance_key(&self, purse_key: Key) -> Result; - /// Gets the balance for a given balance key. - fn get_purse_balance(&self, balance_key: Key) -> Result; + /// Returns the available balance, considering any holds from holds_epoch to now. + /// If holds_epoch is none, available balance == total balance. + fn get_available_balance( + &self, + balance_key: Key, + holds_epoch: HoldsEpoch, + ) -> Result; /// Gets the purse balance key for a given purse and provides a Merkle proof. fn get_purse_balance_key_with_proof( @@ -30,10 +42,25 @@ pub trait TrackingCopyExt { ) -> Result<(Key, TrieMerkleProof), Self::Error>; /// Gets the balance at a given balance key and provides a Merkle proof. - fn get_purse_balance_with_proof( + fn get_total_balance_with_proof( &self, balance_key: Key, - ) -> Result<(Motes, TrieMerkleProof), Self::Error>; + ) -> Result<(U512, TrieMerkleProof), Self::Error>; + + /// Clear expired balance holds. + fn clear_expired_balance_holds( + &mut self, + purse_addr: URefAddr, + tag: BalanceHoldAddrTag, + holds_epoch: HoldsEpoch, + ) -> Result<(), Self::Error>; + + /// Gets the balance holds for a given balance, with Merkle proofs. + fn get_balance_holds_with_proof( + &self, + purse_addr: URefAddr, + holds_epoch: HoldsEpoch, + ) -> Result, Self::Error>; /// Returns the collection of named keys for a given AddressableEntity. fn get_named_keys(&mut self, entity_addr: EntityAddr) -> Result; @@ -41,7 +68,7 @@ pub trait TrackingCopyExt { /// Gets a package by hash. fn get_package(&mut self, package_hash: PackageHash) -> Result; - /// Gets the system contract registry. + /// Gets the system entity registry. fn get_system_entity_registry(&mut self) -> Result; /// Gets the system checksum registry. @@ -75,15 +102,61 @@ where Ok(Key::Balance(balance_key.addr())) } - fn get_purse_balance(&self, key: Key) -> Result { - let stored_value: StoredValue = self - .read(&key)? - .ok_or(TrackingCopyError::KeyNotFound(key))?; - let cl_value: CLValue = stored_value - .try_into() - .map_err(TrackingCopyError::TypeMismatch)?; - let balance = Motes::new(cl_value.into_t()?); - Ok(balance) + fn get_available_balance( + &self, + key: Key, + holds_epoch: HoldsEpoch, + ) -> Result { + let key = { + if let Key::URef(uref) = key { + Key::Balance(uref.addr()) + } else { + key + } + }; + + if let Key::Balance(purse_addr) = key { + let stored_value: StoredValue = self + .read(&key)? + .ok_or(TrackingCopyError::KeyNotFound(key))?; + let cl_value: CLValue = stored_value + .try_into() + .map_err(TrackingCopyError::TypeMismatch)?; + let total_balance = cl_value.into_t::()?; + match holds_epoch.value() { + None => Ok(Motes::new(total_balance)), + Some(epoch) => { + let mut total_holds = U512::zero(); + let tag = BalanceHoldAddrTag::Gas; + let prefix = tag.purse_prefix_by_tag(purse_addr)?; + let gas_hold_keys = self.keys_with_prefix(&prefix)?; + for gas_hold_key in gas_hold_keys { + if let Some(balance_hold_addr) = gas_hold_key.as_balance_hold() { + let block_time = balance_hold_addr.block_time(); + if block_time.value() < epoch { + // ignore holds from prior to imputed epoch + continue; + } + let stored_value: StoredValue = self + .read(&gas_hold_key)? + .ok_or(TrackingCopyError::KeyNotFound(key))?; + let cl_value: CLValue = stored_value + .try_into() + .map_err(TrackingCopyError::TypeMismatch)?; + let hold_amount = cl_value.into_t()?; + total_holds = + total_holds.checked_add(hold_amount).unwrap_or(U512::zero()); + } + } + let available = total_balance + .checked_sub(total_holds) + .unwrap_or(U512::zero()); + Ok(Motes::new(available)) + } + } + } else { + Err(Self::Error::UnexpectedKeyVariant(key)) + } } fn get_purse_balance_key_with_proof( @@ -105,20 +178,102 @@ where Ok((balance_key, proof)) } - fn get_purse_balance_with_proof( + fn get_total_balance_with_proof( &self, key: Key, - ) -> Result<(Motes, TrieMerkleProof), Self::Error> { - let proof: TrieMerkleProof = self - .read_with_proof(&key.normalize())? - .ok_or(TrackingCopyError::KeyNotFound(key))?; - let cl_value: CLValue = proof - .value() - .to_owned() - .try_into() - .map_err(TrackingCopyError::TypeMismatch)?; - let balance = Motes::new(cl_value.into_t()?); - Ok((balance, proof)) + ) -> Result<(U512, TrieMerkleProof), Self::Error> { + if let Key::Balance(_) = key { + let proof: TrieMerkleProof = self + .read_with_proof(&key.normalize())? + .ok_or(TrackingCopyError::KeyNotFound(key))?; + let cl_value: CLValue = proof + .value() + .to_owned() + .try_into() + .map_err(TrackingCopyError::TypeMismatch)?; + let balance = cl_value.into_t()?; + Ok((balance, proof)) + } else { + Err(Self::Error::UnexpectedKeyVariant(key)) + } + } + + fn clear_expired_balance_holds( + &mut self, + purse_addr: URefAddr, + tag: BalanceHoldAddrTag, + holds_epoch: HoldsEpoch, + ) -> Result<(), Self::Error> { + let prefix = tag.purse_prefix_by_tag(purse_addr)?; + let immut: &_ = self; + let gas_hold_keys = immut.keys_with_prefix(&prefix)?; + for gas_hold_key in gas_hold_keys { + if let Some(balance_hold_addr) = gas_hold_key.as_balance_hold() { + let block_time = balance_hold_addr.block_time(); + if let Some(timestamp) = holds_epoch.value() { + if block_time.value() >= timestamp { + // skip still current holds + continue; + } + } + // prune outdated holds + self.prune(gas_hold_key) + } + } + Ok(()) + } + + fn get_balance_holds_with_proof( + &self, + purse_addr: URefAddr, + holds_epoch: HoldsEpoch, + ) -> Result, Self::Error> { + let mut ret: BTreeMap = BTreeMap::new(); + let tag = BalanceHoldAddrTag::Gas; + let prefix = tag.purse_prefix_by_tag(purse_addr)?; + let gas_hold_keys = self.keys_with_prefix(&prefix)?; + // if more hold kinds are added, chain them here and loop once. + for gas_hold_key in gas_hold_keys { + if let Some(balance_hold_addr) = gas_hold_key.as_balance_hold() { + let block_time = balance_hold_addr.block_time(); + if let Some(timestamp) = holds_epoch.value() { + if block_time.value() < timestamp { + // ignore holds older than the interval + continue; + } + } + let proof: TrieMerkleProof = self + .read_with_proof(&gas_hold_key.normalize())? + .ok_or(TrackingCopyError::KeyNotFound(gas_hold_key))?; + let cl_value: CLValue = proof + .value() + .to_owned() + .try_into() + .map_err(TrackingCopyError::TypeMismatch)?; + let hold_amount = cl_value.into_t()?; + match ret.entry(block_time) { + Entry::Vacant(entry) => { + let mut inner = BTreeMap::new(); + inner.insert(tag, (hold_amount, proof)); + entry.insert(inner); + } + Entry::Occupied(mut occupied_entry) => { + let inner = occupied_entry.get_mut(); + match inner.entry(tag) { + Entry::Vacant(entry) => { + entry.insert((hold_amount, proof)); + } + Entry::Occupied(_) => { + unreachable!( + "there should be only one entry per (block_time, hold kind)" + ); + } + } + } + } + } + } + Ok(ret) } fn get_byte_code(&mut self, byte_code_hash: ByteCodeHash) -> Result { diff --git a/storage/src/tracking_copy/ext_entity.rs b/storage/src/tracking_copy/ext_entity.rs index 135a4011f6..90c415b2cc 100644 --- a/storage/src/tracking_copy/ext_entity.rs +++ b/storage/src/tracking_copy/ext_entity.rs @@ -8,11 +8,11 @@ use casper_types::{ Weight, }, bytesrepr, - package::{EntityVersions, Groups, PackageStatus}, system::{handle_payment::ACCUMULATION_PURSE_KEY, AUCTION, HANDLE_PAYMENT, MINT}, AccessRights, Account, AddressableEntity, AddressableEntityHash, ByteCodeHash, CLValue, - ContextAccessRights, EntityAddr, EntityKind, EntryPoints, Key, Package, PackageHash, Phase, - ProtocolVersion, PublicKey, StoredValue, StoredValueTypeMismatch, URef, + ContextAccessRights, EntityAddr, EntityKind, EntityVersions, EntryPoints, Groups, Key, Package, + PackageHash, PackageStatus, Phase, ProtocolVersion, PublicKey, StoredValue, + StoredValueTypeMismatch, URef, }; use crate::{ @@ -149,9 +149,9 @@ where .get_system_entity_registry()? .has_contract_hash(&entity_hash) { - EntityAddr::new_system_entity_addr(entity_hash.value()) + EntityAddr::new_system(entity_hash.value()) } else { - EntityAddr::new_contract_entity_addr(entity_hash.value()) + EntityAddr::new_smart_contract(entity_hash.value()) }; self.get_addressable_entity(entity_addr) @@ -382,7 +382,7 @@ where package }; - let entity_addr = EntityAddr::new_account_entity_addr(entity_hash.value()); + let entity_addr = EntityAddr::new_account(entity_hash.value()); let entity_key = Key::AddressableEntity(entity_addr); self.write(entity_key, entity.into()); @@ -406,45 +406,22 @@ where ) -> Result<(), Self::Error> { let account_hash = account.account_hash(); - let mut generator = - AddressGenerator::new(account.main_purse().addr().as_ref(), Phase::System); + // carry forward the account hash to allow reverse lookup + let entity_hash = AddressableEntityHash::new(account_hash.value()); + let entity_addr = EntityAddr::new_account(entity_hash.value()); - let byte_code_hash = ByteCodeHash::default(); - let entity_hash = AddressableEntityHash::new(generator.new_hash_address()); - let package_hash = PackageHash::new(generator.new_hash_address()); - - let entry_points = EntryPoints::new(); + // migrate named keys -- if this fails there is no reason to proceed further. + let named_keys = account.named_keys().clone(); + self.migrate_named_keys(entity_addr, named_keys)?; - let associated_keys = AssociatedKeys::from(account.associated_keys().clone()); - let action_thresholds = { - let account_threshold = account.action_thresholds().clone(); - ActionThresholds::new( - Weight::new(account_threshold.deployment.value()), - Weight::new(1u8), - Weight::new(account_threshold.key_management.value()), - ) - .map_err(Self::Error::SetThresholdFailure)? - }; - - let entity_addr = EntityAddr::new_account_entity_addr(entity_hash.value()); - - self.migrate_named_keys(entity_addr, account.named_keys().clone())?; - - let entity = AddressableEntity::new( - package_hash, - byte_code_hash, - entry_points, - protocol_version, - account.main_purse(), - associated_keys, - action_thresholds, - MessageTopics::default(), - EntityKind::Account(account_hash), - ); + // write package first + let package_hash = { + let mut generator = + AddressGenerator::new(account.main_purse().addr().as_ref(), Phase::System); - let access_key = generator.new_uref(AccessRights::READ_ADD_WRITE); + let package_hash = PackageHash::new(generator.new_hash_address()); + let access_key = generator.new_uref(AccessRights::READ_ADD_WRITE); - let package = { let mut package = Package::new( access_key, EntityVersions::default(), @@ -453,22 +430,54 @@ where PackageStatus::Locked, ); package.insert_entity_version(protocol_version.value().major, entity_hash); - package + self.write(package_hash.into(), package.into()); + package_hash }; - let entity_key: Key = entity.entity_key(entity_hash); + // write entity after package + { + // currently, addressable entities of account kind are not permitted to have bytecode + // however, we intend to revisit this and potentially allow it in a future release + // as a replacement for stored session. + let byte_code_hash = ByteCodeHash::default(); + let entry_points = EntryPoints::new(); + + let action_thresholds = { + let account_threshold = account.action_thresholds().clone(); + ActionThresholds::new( + Weight::new(account_threshold.deployment.value()), + Weight::new(1u8), + Weight::new(account_threshold.key_management.value()), + ) + .map_err(Self::Error::SetThresholdFailure)? + }; - self.write(entity_key, entity.into()); - self.write(package_hash.into(), package.into()); - let contract_by_account = match CLValue::from_t(entity_key) { - Ok(cl_value) => cl_value, - Err(err) => return Err(Self::Error::CLValue(err)), - }; + let associated_keys = AssociatedKeys::from(account.associated_keys().clone()); + + let entity = AddressableEntity::new( + package_hash, + byte_code_hash, + entry_points, + protocol_version, + account.main_purse(), + associated_keys, + action_thresholds, + MessageTopics::default(), + EntityKind::Account(account_hash), + ); + let entity_key = entity.entity_key(entity_hash); + let contract_by_account = match CLValue::from_t(entity_key) { + Ok(cl_value) => cl_value, + Err(err) => return Err(Self::Error::CLValue(err)), + }; + + self.write(entity_key, entity.into()); + self.write( + Key::Account(account_hash), + StoredValue::CLValue(contract_by_account), + ); + } - self.write( - Key::Account(account_hash), - StoredValue::CLValue(contract_by_account), - ); Ok(()) } @@ -480,10 +489,10 @@ where let system_entity = self.get_addressable_entity_by_account_hash(protocol_version, system_account_hash)?; - let scr = self.get_system_entity_registry()?; + let system_entity_registry = self.get_system_entity_registry()?; let (auction_named_keys, mut auction_access_rights) = { - let auction_hash = match scr.get(AUCTION).copied() { + let auction_hash = match system_entity_registry.get(AUCTION).copied() { Some(auction_hash) => auction_hash, None => { error!("unexpected failure; auction not found"); @@ -493,15 +502,14 @@ where } }; let auction = self.get_addressable_entity_by_hash(auction_hash)?; - let auction_addr = - EntityAddr::new_with_tag(auction.entity_kind(), auction_hash.value()); + let auction_addr = auction.entity_addr(auction_hash); let auction_named_keys = self.get_named_keys(auction_addr)?; let auction_access_rights = auction.extract_access_rights(auction_hash, &auction_named_keys); (auction_named_keys, auction_access_rights) }; let (mint_named_keys, mint_access_rights) = { - let mint_hash = match scr.get(MINT).copied() { + let mint_hash = match system_entity_registry.get(MINT).copied() { Some(mint_hash) => mint_hash, None => { error!("unexpected failure; mint not found"); @@ -511,14 +519,14 @@ where } }; let mint = self.get_addressable_entity_by_hash(mint_hash)?; - let mint_addr = EntityAddr::new_with_tag(mint.entity_kind(), mint_hash.value()); + let mint_addr = mint.entity_addr(mint_hash); let mint_named_keys = self.get_named_keys(mint_addr)?; let mint_access_rights = mint.extract_access_rights(mint_hash, &mint_named_keys); (mint_named_keys, mint_access_rights) }; let (payment_named_keys, payment_access_rights) = { - let payment_hash = match scr.get(HANDLE_PAYMENT).copied() { + let payment_hash = match system_entity_registry.get(HANDLE_PAYMENT).copied() { Some(payment_hash) => payment_hash, None => { error!("unexpected failure; handle payment not found"); @@ -528,8 +536,7 @@ where } }; let payment = self.get_addressable_entity_by_hash(payment_hash)?; - let payment_addr = - EntityAddr::new_with_tag(payment.entity_kind(), payment_hash.value()); + let payment_addr = payment.entity_addr(payment_hash); let payment_named_keys = self.get_named_keys(payment_addr)?; let payment_access_rights = payment.extract_access_rights(payment_hash, &mint_named_keys); @@ -566,7 +573,7 @@ where authorization_keys, administrative_accounts, )?; - let entity_addr = EntityAddr::new_with_tag(entity.entity_kind(), entity_hash.value()); + let entity_addr = entity.entity_addr(entity_hash); let named_keys = self.get_named_keys(entity_addr)?; let access_rights = entity .extract_access_rights(AddressableEntityHash::new(entity_addr.value()), &named_keys); @@ -599,7 +606,7 @@ where )) } }; - EntityAddr::new_system_entity_addr(hash.value()) + EntityAddr::new_system(hash.value()) }; let named_keys = self.get_named_keys(entity_addr)?; diff --git a/storage/src/tracking_copy/mod.rs b/storage/src/tracking_copy/mod.rs index 25f833ed11..69d5fd0d9c 100644 --- a/storage/src/tracking_copy/mod.rs +++ b/storage/src/tracking_copy/mod.rs @@ -62,6 +62,32 @@ pub enum TrackingCopyQueryResult { }, } +impl TrackingCopyQueryResult { + /// Is this a successful query? + pub fn is_success(&self) -> bool { + matches!(self, TrackingCopyQueryResult::Success { .. }) + } + + /// As result. + pub fn as_result(self) -> Result { + match self { + TrackingCopyQueryResult::RootNotFound => { + Err(TrackingCopyError::Storage(Error::RootNotFound)) + } + TrackingCopyQueryResult::ValueNotFound(msg) => { + Err(TrackingCopyError::ValueNotFound(msg)) + } + TrackingCopyQueryResult::CircularReference(msg) => { + Err(TrackingCopyError::CircularReference(msg)) + } + TrackingCopyQueryResult::DepthLimit { depth } => { + Err(TrackingCopyError::QueryDepthLimit { depth }) + } + TrackingCopyQueryResult::Success { value, .. } => Ok(value), + } + } +} + /// Struct containing state relating to a given query. struct Query { /// The key from where the search starts. @@ -645,8 +671,8 @@ where StoredValue::ByteCode(_) => { return Ok(query.into_not_found_result("ByteCode value found.")); } - StoredValue::Transfer(_) => { - return Ok(query.into_not_found_result("Transfer value found.")); + StoredValue::LegacyTransfer(_) => { + return Ok(query.into_not_found_result("Legacy Transfer value found.")); } StoredValue::DeployInfo(_) => { return Ok(query.into_not_found_result("DeployInfo value found.")); @@ -896,9 +922,12 @@ pub fn validate_balance_proof( Ok(()) } -use crate::global_state::state::{ - lmdb::{make_temporary_global_state, LmdbGlobalStateView}, - StateProvider, +use crate::global_state::{ + error::Error, + state::{ + lmdb::{make_temporary_global_state, LmdbGlobalStateView}, + StateProvider, + }, }; use tempfile::TempDir; diff --git a/types/benches/bytesrepr_bench.rs b/types/benches/bytesrepr_bench.rs index ae4ba66f8f..35a074a5dd 100644 --- a/types/benches/bytesrepr_bench.rs +++ b/types/benches/bytesrepr_bench.rs @@ -11,13 +11,13 @@ use casper_types::{ ActionThresholds, AddressableEntity, AssociatedKeys, EntityKind, MessageTopics, }, bytesrepr::{self, Bytes, FromBytes, ToBytes}, - package::PackageStatus, system::auction::{Bid, Delegator, EraInfo, SeigniorageAllocation}, AccessRights, AddressableEntityHash, ByteCodeHash, CLType, CLTyped, CLValue, DeployHash, DeployInfo, EntityVersionKey, EntityVersions, EntryPoint, EntryPointAccess, EntryPointType, - EntryPoints, Group, Groups, Key, Package, PackageHash, Parameter, ProtocolVersion, PublicKey, - SecretKey, Transfer, TransferAddr, URef, KEY_HASH_LENGTH, TRANSFER_ADDR_LENGTH, U128, U256, - U512, UREF_ADDR_LENGTH, + EntryPoints, Gas, Group, Groups, InitiatorAddr, Key, Package, PackageHash, PackageStatus, + Parameter, ProtocolVersion, PublicKey, SecretKey, TransactionHash, TransactionV1Hash, + TransferAddr, TransferV2, URef, KEY_HASH_LENGTH, TRANSFER_ADDR_LENGTH, U128, U256, U512, + UREF_ADDR_LENGTH, }; static KB: usize = 1024; @@ -473,7 +473,7 @@ fn sample_contract(entry_points_len: u8) -> AddressableEntity { args, casper_types::CLType::U512, EntryPointAccess::groups(&["Group 2"]), - EntryPointType::AddressableEntity, + EntryPointType::Called, ); tmp.add_entry_point(entry_point); }); @@ -620,28 +620,28 @@ fn deserialize_bid(delegators_len: u32, b: &mut Bencher) { b.iter(|| Bid::from_bytes(black_box(&bid_bytes))); } -fn sample_transfer() -> Transfer { - Transfer::new( - DeployHash::default(), - AccountHash::default(), +fn sample_transfer() -> TransferV2 { + TransferV2::new( + TransactionHash::V1(TransactionV1Hash::default()), + InitiatorAddr::AccountHash(AccountHash::default()), None, URef::default(), URef::default(), U512::MAX, - U512::from_dec_str("123123123123").unwrap(), + Gas::new(U512::from_dec_str("123123123123").unwrap()), Some(1u64), ) } fn serialize_transfer(b: &mut Bencher) { let transfer = sample_transfer(); - b.iter(|| Transfer::to_bytes(&transfer)); + b.iter(|| TransferV2::to_bytes(&transfer)); } fn deserialize_transfer(b: &mut Bencher) { let transfer = sample_transfer(); let transfer_bytes = transfer.to_bytes().unwrap(); - b.iter(|| Transfer::from_bytes(&transfer_bytes)); + b.iter(|| TransferV2::from_bytes(&transfer_bytes)); } fn sample_deploy_info(transfer_len: u16) -> DeployInfo { diff --git a/types/src/addressable_entity.rs b/types/src/addressable_entity.rs index 4bc2902f3d..a5d49c45c7 100644 --- a/types/src/addressable_entity.rs +++ b/types/src/addressable_entity.rs @@ -57,7 +57,6 @@ pub use self::{ named_keys::NamedKeys, weight::{Weight, WEIGHT_SERIALIZED_LENGTH}, }; - use crate::{ account::{Account, AccountHash}, byte_code::ByteCodeHash, @@ -77,18 +76,9 @@ pub const MAX_GROUPS: u8 = 10; /// Maximum number of URefs which can be assigned across all user groups. pub const MAX_TOTAL_UREFS: usize = 100; -/// The tag for Contract Packages associated with Wasm stored on chain. -pub const PACKAGE_KIND_WASM_TAG: u8 = 0; -/// The tag for Contract Package associated with a native contract implementation. -pub const PACKAGE_KIND_SYSTEM_CONTRACT_TAG: u8 = 1; -/// The tag for Contract Package associated with an Account hash. -pub const PACKAGE_KIND_ACCOUNT_TAG: u8 = 2; -/// The tag for Contract Packages associated with legacy packages. -pub const PACKAGE_KIND_LEGACY_TAG: u8 = 3; - const ADDRESSABLE_ENTITY_STRING_PREFIX: &str = "addressable-entity-"; -const ENTITY_PREFIX: &str = "addressable-entity-"; +const ENTITY_PREFIX: &str = "entity-"; const ACCOUNT_ENTITY_PREFIX: &str = "account-"; const CONTRACT_ENTITY_PREFIX: &str = "contract-"; const SYSTEM_ENTITY_PREFIX: &str = "system-"; @@ -262,6 +252,11 @@ impl AddressableEntityHash { AddressableEntityHash(value) } + /// Get the entity addr for this entity hash from the corresponding entity. + pub fn entity_addr(&self, entity: AddressableEntity) -> EntityAddr { + entity.entity_addr(*self) + } + /// Returns the raw bytes of the contract hash as an array. pub fn value(&self) -> HashAddr { self.0 @@ -654,7 +649,7 @@ impl EntryPoints { pub fn contains_stored_session(&self) -> bool { self.0 .values() - .any(|entry_point| entry_point.entry_point_type == EntryPointType::Session) + .any(|entry_point| entry_point.entry_point_type == EntryPointType::Caller) } } @@ -680,13 +675,16 @@ impl KeyValueJsonSchema for EntryPointLabels { const JSON_SCHEMA_KV_NAME: Option<&'static str> = Some("NamedEntryPoint"); } -#[allow(missing_docs)] +/// Tag for the variants of [`EntityKind`]. #[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)] #[cfg_attr(feature = "datasize", derive(DataSize))] #[repr(u8)] pub enum EntityKindTag { + /// `EntityKind::System` variant. System = 0, + /// `EntityKind::Account` variant. Account = 1, + /// `EntityKind::SmartContract` variant. SmartContract = 2, } @@ -885,14 +883,14 @@ impl FromBytes for EntityKind { impl Display for EntityKind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - EntityKind::SmartContract => { - write!(f, "PackageKind:Wasm") - } EntityKind::System(system_entity) => { - write!(f, "PackageKind:System({})", system_entity) + write!(f, "system-entity-kind({})", system_entity) } EntityKind::Account(account_hash) => { - write!(f, "PackageKind:Account({})", account_hash) + write!(f, "account-entity-kind({})", account_hash) + } + EntityKind::SmartContract => { + write!(f, "smart-contract-entity-kind") } } } @@ -924,30 +922,30 @@ pub enum EntityAddr { } impl EntityAddr { - /// The length in bytes of a [`EntityAddr`]. - pub const ENTITY_ADDR_LENGTH: usize = U8_SERIALIZED_LENGTH + KEY_HASH_LENGTH; + /// The length in bytes of an `EntityAddr`. + pub const LENGTH: usize = U8_SERIALIZED_LENGTH + KEY_HASH_LENGTH; - /// Constructs a new [`EntityAddr`] for a system entity. - pub const fn new_system_entity_addr(hash_addr: [u8; KEY_HASH_LENGTH]) -> Self { + /// Constructs a new `EntityAddr` for a system entity. + pub const fn new_system(hash_addr: HashAddr) -> Self { Self::System(hash_addr) } - /// Constructs a new [`EntityAddr`] for an Account entity. - pub const fn new_account_entity_addr(hash_addr: [u8; KEY_HASH_LENGTH]) -> Self { + /// Constructs a new `EntityAddr` for an Account entity. + pub const fn new_account(hash_addr: HashAddr) -> Self { Self::Account(hash_addr) } - /// Constructs a new [`EntityAddr`] for a smart contract. - pub const fn new_contract_entity_addr(hash_addr: [u8; KEY_HASH_LENGTH]) -> Self { + /// Constructs a new `EntityAddr` for a smart contract. + pub const fn new_smart_contract(hash_addr: HashAddr) -> Self { Self::SmartContract(hash_addr) } - /// Constructs a new [`EntityAddr`] based on the supplied tag. - pub fn new_with_tag(entity_kind: EntityKind, hash_addr: [u8; KEY_HASH_LENGTH]) -> Self { + /// Constructs a new `EntityAddr` based on the supplied kind. + pub fn new_of_kind(entity_kind: EntityKind, hash_addr: HashAddr) -> Self { match entity_kind { - EntityKind::System(_) => Self::new_system_entity_addr(hash_addr), - EntityKind::Account(_) => Self::new_account_entity_addr(hash_addr), - EntityKind::SmartContract => Self::new_contract_entity_addr(hash_addr), + EntityKind::System(_) => Self::new_system(hash_addr), + EntityKind::Account(_) => Self::new_account(hash_addr), + EntityKind::SmartContract => Self::new_smart_contract(hash_addr), } } @@ -960,6 +958,12 @@ impl EntityAddr { } } + /// Is this a system entity address? + pub fn is_system(&self) -> bool { + self.tag() == EntityKindTag::System + || self.value() == PublicKey::System.to_account_hash().value() + } + /// Returns the 32 bytes of the [`EntityAddr`]. pub fn value(&self) -> HashAddr { match self { @@ -979,16 +983,41 @@ impl EntityAddr { /// Returns the formatted String representation of the [`EntityAddr`]. pub fn to_formatted_string(&self) -> String { - format!("{}", self) + match self { + EntityAddr::System(addr) => { + format!( + "{}{}{}", + ENTITY_PREFIX, + SYSTEM_ENTITY_PREFIX, + base16::encode_lower(addr) + ) + } + EntityAddr::Account(addr) => { + format!( + "{}{}{}", + ENTITY_PREFIX, + ACCOUNT_ENTITY_PREFIX, + base16::encode_lower(addr) + ) + } + EntityAddr::SmartContract(addr) => { + format!( + "{}{}{}", + ENTITY_PREFIX, + CONTRACT_ENTITY_PREFIX, + base16::encode_lower(addr) + ) + } + } } /// Constructs an [`EntityAddr`] from a formatted String. pub fn from_formatted_str(input: &str) -> Result { if let Some(entity) = input.strip_prefix(ENTITY_PREFIX) { - let (addr_str, tag) = if let Some(str) = entity.strip_prefix(ACCOUNT_ENTITY_PREFIX) { - (str, EntityKindTag::Account) - } else if let Some(str) = entity.strip_prefix(SYSTEM_ENTITY_PREFIX) { + let (addr_str, tag) = if let Some(str) = entity.strip_prefix(SYSTEM_ENTITY_PREFIX) { (str, EntityKindTag::System) + } else if let Some(str) = entity.strip_prefix(ACCOUNT_ENTITY_PREFIX) { + (str, EntityKindTag::Account) } else if let Some(str) = entity.strip_prefix(CONTRACT_ENTITY_PREFIX) { (str, EntityKindTag::SmartContract) } else { @@ -997,9 +1026,9 @@ impl EntityAddr { let addr = checksummed_hex::decode(addr_str).map_err(FromStrError::Hex)?; let hash_addr = HashAddr::try_from(addr.as_ref()).map_err(FromStrError::Hash)?; let entity_addr = match tag { - EntityKindTag::System => EntityAddr::new_system_entity_addr(hash_addr), - EntityKindTag::Account => EntityAddr::new_account_entity_addr(hash_addr), - EntityKindTag::SmartContract => EntityAddr::new_contract_entity_addr(hash_addr), + EntityKindTag::System => EntityAddr::new_system(hash_addr), + EntityKindTag::Account => EntityAddr::new_account(hash_addr), + EntityKindTag::SmartContract => EntityAddr::new_smart_contract(hash_addr), }; return Ok(entity_addr); @@ -1012,39 +1041,45 @@ impl EntityAddr { impl ToBytes for EntityAddr { fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; - buffer.push(self.tag() as u8); - buffer.append(&mut self.value().to_bytes()?); + self.write_bytes(&mut buffer)?; Ok(buffer) } fn serialized_length(&self) -> usize { - EntityAddr::ENTITY_ADDR_LENGTH + EntityAddr::LENGTH } -} -impl FromBytes for EntityAddr { - fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { - let (tag, remainder): (EntityKindTag, &[u8]) = FromBytes::from_bytes(bytes)?; - match tag { - EntityKindTag::System => { - HashAddr::from_bytes(remainder).map(|(hash_addr, remainder)| { - (EntityAddr::new_system_entity_addr(hash_addr), remainder) - }) + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + match self { + EntityAddr::System(addr) => { + EntityKindTag::System.write_bytes(writer)?; + addr.write_bytes(writer) } - EntityKindTag::Account => { - HashAddr::from_bytes(remainder).map(|(hash_addr, remainder)| { - (EntityAddr::new_account_entity_addr(hash_addr), remainder) - }) + EntityAddr::Account(addr) => { + EntityKindTag::Account.write_bytes(writer)?; + addr.write_bytes(writer) } - EntityKindTag::SmartContract => { - HashAddr::from_bytes(remainder).map(|(hash_addr, remainder)| { - (EntityAddr::new_contract_entity_addr(hash_addr), remainder) - }) + EntityAddr::SmartContract(addr) => { + EntityKindTag::SmartContract.write_bytes(writer)?; + addr.write_bytes(writer) } } } } +impl FromBytes for EntityAddr { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (tag, remainder) = EntityKindTag::from_bytes(bytes)?; + let (addr, remainder) = HashAddr::from_bytes(remainder)?; + let entity_addr = match tag { + EntityKindTag::System => EntityAddr::System(addr), + EntityKindTag::Account => EntityAddr::Account(addr), + EntityKindTag::SmartContract => EntityAddr::SmartContract(addr), + }; + Ok((entity_addr, remainder)) + } +} + impl From for AddressableEntityHash { fn from(entity_addr: EntityAddr) -> Self { AddressableEntityHash::new(entity_addr.value()) @@ -1053,13 +1088,7 @@ impl From for AddressableEntityHash { impl Display for EntityAddr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!( - f, - "{}{}-{}", - ADDRESSABLE_ENTITY_STRING_PREFIX, - self.tag(), - base16::encode_lower(&self.value()) - ) + f.write_str(&self.to_formatted_string()) } } @@ -1067,13 +1096,21 @@ impl Debug for EntityAddr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { EntityAddr::System(hash_addr) => { - write!(f, "EntityAddr::System({:?})", hash_addr) + write!(f, "EntityAddr::System({})", base16::encode_lower(hash_addr)) } EntityAddr::Account(hash_addr) => { - write!(f, "EntityAddr::Account({:?})", hash_addr) + write!( + f, + "EntityAddr::Account({})", + base16::encode_lower(hash_addr) + ) } EntityAddr::SmartContract(hash_addr) => { - write!(f, "EntityAddr::SmartContract({:?})", hash_addr) + write!( + f, + "EntityAddr::SmartContract({})", + base16::encode_lower(hash_addr) + ) } } } @@ -1105,7 +1142,7 @@ pub struct NamedKeyAddr { impl NamedKeyAddr { /// The length in bytes of a [`NamedKeyAddr`]. - pub const NAMED_KEY_ADDR_BASE_LENGTH: usize = 1 + EntityAddr::ENTITY_ADDR_LENGTH; + pub const NAMED_KEY_ADDR_BASE_LENGTH: usize = 1 + EntityAddr::LENGTH; /// Constructs a new [`NamedKeyAddr`] based on the supplied bytes. pub const fn new_named_key_entry( @@ -1160,6 +1197,15 @@ impl NamedKeyAddr { } } +impl Default for NamedKeyAddr { + fn default() -> Self { + NamedKeyAddr { + base_addr: EntityAddr::System(HashAddr::default()), + string_bytes: Default::default(), + } + } +} + impl ToBytes for NamedKeyAddr { fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; @@ -1492,6 +1538,16 @@ impl AddressableEntity { } } + /// Get the entity addr for this entity from the corresponding hash. + pub fn entity_addr(&self, entity_hash: AddressableEntityHash) -> EntityAddr { + let hash_addr = entity_hash.value(); + match self.entity_kind { + EntityKind::System(_) => EntityAddr::new_system(hash_addr), + EntityKind::Account(_) => EntityAddr::new_account(hash_addr), + EntityKind::SmartContract => EntityAddr::new_smart_contract(hash_addr), + } + } + /// Hash for accessing contract package pub fn package_hash(&self) -> PackageHash { self.package_hash @@ -1737,8 +1793,8 @@ impl AddressableEntity { false } - /// Returns the kind of Package. - pub fn entity_kind(&self) -> EntityKind { + /// Returns the kind of `AddressableEntity`. + pub fn kind(&self) -> EntityKind { self.entity_kind } @@ -1813,7 +1869,7 @@ impl ToBytes for AddressableEntity { self.associated_keys().write_bytes(&mut result)?; self.action_thresholds().write_bytes(&mut result)?; self.message_topics().write_bytes(&mut result)?; - self.entity_kind().write_bytes(&mut result)?; + self.kind().write_bytes(&mut result)?; Ok(result) } @@ -1838,7 +1894,7 @@ impl ToBytes for AddressableEntity { self.associated_keys().write_bytes(writer)?; self.action_thresholds().write_bytes(writer)?; self.message_topics().write_bytes(writer)?; - self.entity_kind().write_bytes(writer)?; + self.kind().write_bytes(writer)?; Ok(()) } } @@ -1928,13 +1984,21 @@ impl From for AddressableEntity { #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] pub enum EntryPointType { - /// Runs as session code (caller) - /// Deprecated, retained to allow read back of legacy stored session. - Session = 0b00000000, - /// Runs within called entity's context (called) - AddressableEntity = 0b00000001, - /// This entry point is intended to extract a subset of bytecode. - /// Runs within called entity's context (called) + /// Runs using the calling entity's context. + /// In v1.x this was used for both "session" code run using the originating + /// Account's context, and also for "StoredSession" code that ran in the + /// caller's context. While this made systemic sense due to the way the runtime + /// context nesting works, this dual usage was very confusing to most human beings. + /// + /// In v2.x the renamed Caller variant is exclusively used for wasm run using the initiating + /// account entity's context. Previously installed 1.x stored session code should + /// continue to work as the binary value matches but we no longer allow such logic + /// to be upgraded, nor do we allow new stored session to be installed. + Caller = 0b00000000, + /// Runs using the called entity's context. + Called = 0b00000001, + /// Extract a subset of bytecode and installs it as a new smart contract. + /// Runs using the called entity's context. Factory = 0b10000000, } @@ -1956,8 +2020,8 @@ impl EntryPointType { /// Returns true if entry point type is invalid for the context. pub fn is_invalid_context(&self) -> bool { match self { - EntryPointType::Session => true, - EntryPointType::AddressableEntity | EntryPointType::Factory => false, + EntryPointType::Caller => true, + EntryPointType::Called | EntryPointType::Factory => false, } } } @@ -2083,7 +2147,7 @@ impl Default for EntryPoint { args: Vec::new(), ret: CLType::Unit, access: EntryPointAccess::Public, - entry_point_type: EntryPointType::Session, + entry_point_type: EntryPointType::Caller, } } } @@ -2327,10 +2391,8 @@ mod tests { #[test] fn named_key_addr_from_str() { - let named_key_addr = NamedKeyAddr::new_named_key_entry( - EntityAddr::new_contract_entity_addr([3; 32]), - [4; 32], - ); + let named_key_addr = + NamedKeyAddr::new_named_key_entry(EntityAddr::new_smart_contract([3; 32]), [4; 32]); let encoded = named_key_addr.to_formatted_string(); let decoded = NamedKeyAddr::from_formatted_str(&encoded).unwrap(); assert_eq!(named_key_addr, decoded); @@ -2362,11 +2424,11 @@ mod tests { #[test] fn serialization_roundtrip() { - let entity_addr = EntityAddr::new_system_entity_addr([1; 32]); + let entity_addr = EntityAddr::new_system([1; 32]); bytesrepr::test_serialization_roundtrip(&entity_addr); - let entity_addr = EntityAddr::new_account_entity_addr([1; 32]); + let entity_addr = EntityAddr::new_account([1; 32]); bytesrepr::test_serialization_roundtrip(&entity_addr); - let entity_addr = EntityAddr::new_contract_entity_addr([1; 32]); + let entity_addr = EntityAddr::new_smart_contract([1; 32]); bytesrepr::test_serialization_roundtrip(&entity_addr); } diff --git a/types/src/api_error.rs b/types/src/api_error.rs index b9504b6f12..3979456573 100644 --- a/types/src/api_error.rs +++ b/types/src/api_error.rs @@ -439,6 +439,13 @@ pub enum ApiError { /// assert_eq!(ApiError::from(47), ApiError::MaxMessagesPerBlockExceeded); /// ``` MaxMessagesPerBlockExceeded, + /// Attempt to call FFI function `casper_add_contract_version()` from a transaction not defined + /// as an installer/upgrader. + /// ``` + /// # use casper_types::ApiError; + /// assert_eq!(ApiError::from(48), ApiError::NotAllowedToAddContractVersion); + /// ``` + NotAllowedToAddContractVersion, } impl From for ApiError { @@ -602,6 +609,7 @@ impl From for u32 { ApiError::MessageTopicFull => 45, ApiError::MessageTooLarge => 46, ApiError::MaxMessagesPerBlockExceeded => 47, + ApiError::NotAllowedToAddContractVersion => 48, ApiError::AuctionError(value) => AUCTION_ERROR_OFFSET + u32::from(value), ApiError::ContractHeader(value) => HEADER_ERROR_OFFSET + u32::from(value), ApiError::Mint(value) => MINT_ERROR_OFFSET + u32::from(value), @@ -661,6 +669,7 @@ impl From for ApiError { 45 => ApiError::MessageTopicFull, 46 => ApiError::MessageTooLarge, 47 => ApiError::MaxMessagesPerBlockExceeded, + 48 => ApiError::NotAllowedToAddContractVersion, USER_ERROR_MIN..=USER_ERROR_MAX => ApiError::User(value as u16), HP_ERROR_MIN..=HP_ERROR_MAX => ApiError::HandlePayment(value as u8), MINT_ERROR_MIN..=MINT_ERROR_MAX => ApiError::Mint(value as u8), @@ -732,6 +741,9 @@ impl Debug for ApiError { ApiError::MaxMessagesPerBlockExceeded => { write!(f, "ApiError::MaxMessagesPerBlockExceeded")? } + ApiError::NotAllowedToAddContractVersion => { + write!(f, "ApiError::NotAllowedToAddContractVersion")? + } ApiError::ExceededRecursionDepth => write!(f, "ApiError::ExceededRecursionDepth")?, ApiError::AuctionError(value) => write!( f, @@ -957,5 +969,6 @@ mod tests { round_trip(Err(ApiError::MessageTopicNotRegistered)); round_trip(Err(ApiError::MessageTopicFull)); round_trip(Err(ApiError::MessageTooLarge)); + round_trip(Err(ApiError::NotAllowedToAddContractVersion)); } } diff --git a/types/src/block.rs b/types/src/block.rs index 273ed87da3..e2cf94b39e 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -29,10 +29,15 @@ use std::error::Error as StdError; #[cfg(feature = "datasize")] use datasize::DataSize; +#[cfg(feature = "std")] +use num_rational::Ratio; #[cfg(feature = "json-schema")] use schemars::JsonSchema; +#[cfg(feature = "std")] +use crate::TransactionConfig; + use crate::{ bytesrepr, bytesrepr::{FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, @@ -393,6 +398,41 @@ impl Block { } } + /// Returns the utilization of the block against a given chainspec. + #[cfg(feature = "std")] + pub fn block_utilization(&self, transaction_config: TransactionConfig) -> u64 { + match self { + Block::V1(_) => { + // We shouldnt be tracking this for legacy blocks + 0 + } + Block::V2(block_v2) => { + let has_hit_slot_limt = { + (block_v2.mint().count() as u32 >= transaction_config.block_max_mint_count) + || (block_v2.auction().count() as u32 + >= transaction_config.block_max_auction_count) + || (block_v2.standard().count() as u32 + >= transaction_config.block_max_standard_count) + || (block_v2.install_upgrade().count() as u32 + >= transaction_config.block_max_install_upgrade_count) + }; + + let per_block_capacity = (transaction_config.block_max_mint_count + + transaction_config.block_max_auction_count + + transaction_config.block_max_standard_count + + transaction_config.block_max_install_upgrade_count) + as u64; + + if has_hit_slot_limt { + 100u64 + } else { + let num = block_v2.all_transactions().count() as u64; + Ratio::new(num * 100, per_block_capacity).to_integer() + } + } + } + } + // This method is not intended to be used by third party crates. #[doc(hidden)] #[cfg(feature = "json-schema")] diff --git a/types/src/block/available_block_range.rs b/types/src/block/available_block_range.rs index 99c2fe321e..5022d366c0 100644 --- a/types/src/block/available_block_range.rs +++ b/types/src/block/available_block_range.rs @@ -7,11 +7,10 @@ use serde::{Deserialize, Serialize}; use crate::bytesrepr::{self, FromBytes, ToBytes}; -#[cfg(test)] -use rand::Rng; - -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; +#[cfg(any(feature = "testing", test))] +use rand::Rng; /// An unbroken, inclusive range of blocks. #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] @@ -52,8 +51,9 @@ impl AvailableBlockRange { self.high } - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { let low = rng.gen::() as u64; let high = low + rng.gen::() as u64; Self { low, high } diff --git a/types/src/block/block_identifier.rs b/types/src/block/block_identifier.rs index 02508bdd0a..dd8e1329e7 100644 --- a/types/src/block/block_identifier.rs +++ b/types/src/block/block_identifier.rs @@ -1,12 +1,13 @@ use alloc::vec::Vec; use core::num::ParseIntError; -#[cfg(test)] + +#[cfg(any(feature = "testing", test))] use rand::Rng; #[cfg(feature = "json-schema")] use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, @@ -28,8 +29,9 @@ pub enum BlockIdentifier { } impl BlockIdentifier { - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { match rng.gen_range(0..1) { 0 => Self::Hash(BlockHash::random(rng)), 1 => Self::Height(rng.gen()), diff --git a/types/src/block/block_sync_status.rs b/types/src/block/block_sync_status.rs index 6c8428242b..36f201294b 100644 --- a/types/src/block/block_sync_status.rs +++ b/types/src/block/block_sync_status.rs @@ -10,11 +10,10 @@ use crate::{ BlockHash, }; -#[cfg(test)] -use rand::Rng; - -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; +#[cfg(any(feature = "testing", test))] +use rand::Rng; #[cfg(feature = "json-schema")] static BLOCK_SYNCHRONIZER_STATUS: Lazy = Lazy::new(|| { @@ -71,8 +70,9 @@ impl BlockSyncStatus { } } - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { Self { block_hash: BlockHash::random(rng), block_height: rng.gen::().then_some(rng.gen()), @@ -143,8 +143,9 @@ impl BlockSynchronizerStatus { &BLOCK_SYNCHRONIZER_STATUS } - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { let historical = rng.gen::().then_some(BlockSyncStatus::random(rng)); let forward = rng.gen::().then_some(BlockSyncStatus::random(rng)); Self { diff --git a/types/src/block/block_v2.rs b/types/src/block/block_v2.rs index 793b36f028..e8eeff694d 100644 --- a/types/src/block/block_v2.rs +++ b/types/src/block/block_v2.rs @@ -242,12 +242,12 @@ impl BlockV2 { } /// Returns the hashes of the transfer transactions within the block. - pub fn transfer(&self) -> impl Iterator { + pub fn mint(&self) -> impl Iterator { self.body.mint() } /// Returns the hashes of the non-transfer, native transactions within the block. - pub fn staking(&self) -> impl Iterator { + pub fn auction(&self) -> impl Iterator { self.body.auction() } diff --git a/types/src/block/signed_block_header.rs b/types/src/block/signed_block_header.rs index e088b74b2b..7e69ecebb6 100644 --- a/types/src/block/signed_block_header.rs +++ b/types/src/block/signed_block_header.rs @@ -9,6 +9,8 @@ use serde::{Deserialize, Serialize}; use super::{BlockHash, BlockHeader, BlockSignatures}; use crate::EraId; +#[cfg(doc)] +use crate::Signature; /// An error which can result from validating a [`SignedBlockHeader`]. #[derive(Copy, Clone, Eq, PartialEq, Debug)] diff --git a/types/src/block_time.rs b/types/src/block_time.rs index 0fb695f61e..4fe4f73533 100644 --- a/types/src/block_time.rs +++ b/types/src/block_time.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use crate::{ bytesrepr::{Error, FromBytes, ToBytes, U64_SERIALIZED_LENGTH}, - CLType, CLTyped, + CLType, CLTyped, TimeDiff, Timestamp, }; #[cfg(feature = "datasize")] @@ -14,11 +14,44 @@ use serde::{Deserialize, Serialize}; /// The number of bytes in a serialized [`BlockTime`]. pub const BLOCKTIME_SERIALIZED_LENGTH: usize = U64_SERIALIZED_LENGTH; +/// Holds epoch type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub struct HoldsEpoch(Option); + +impl HoldsEpoch { + /// No epoch is applicable. + pub const NOT_APPLICABLE: HoldsEpoch = HoldsEpoch(None); + + /// Instance from block time. + pub fn from_block_time(block_time: BlockTime, hold_internal: TimeDiff) -> Self { + HoldsEpoch(Some( + block_time.value().saturating_sub(hold_internal.millis()), + )) + } + + /// Instance from timestamp. + pub fn from_timestamp(timestamp: Timestamp, hold_internal: TimeDiff) -> Self { + HoldsEpoch(Some( + timestamp.millis().saturating_sub(hold_internal.millis()), + )) + } + + /// Instance from milliseconds. + pub fn from_millis(timestamp_millis: u64, hold_internal_millis: u64) -> Self { + HoldsEpoch(Some(timestamp_millis.saturating_sub(hold_internal_millis))) + } + + /// Returns the inner value. + pub fn value(&self) -> Option { + self.0 + } +} + /// A newtype wrapping a [`u64`] which represents the block time. #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] #[derive( - Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, + Clone, Copy, Default, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, )] pub struct BlockTime(u64); @@ -47,6 +80,24 @@ impl From for u64 { } } +impl From for Timestamp { + fn from(value: BlockTime) -> Self { + Timestamp::from(value.0) + } +} + +impl From for BlockTime { + fn from(value: u64) -> Self { + BlockTime(value) + } +} + +impl From for BlockTime { + fn from(value: Timestamp) -> Self { + BlockTime(value.millis()) + } +} + impl ToBytes for BlockTime { fn to_bytes(&self) -> Result, Error> { self.0.to_bytes() diff --git a/types/src/chainspec.rs b/types/src/chainspec.rs index 6b5712f75e..024412dd02 100644 --- a/types/src/chainspec.rs +++ b/types/src/chainspec.rs @@ -11,6 +11,7 @@ mod global_state_update; mod highway_config; mod network_config; mod next_upgrade; +mod pricing_handling; mod protocol_config; mod refund_handling; mod transaction_config; @@ -18,6 +19,7 @@ mod upgrade_config; mod vacancy_config; mod vm_config; +#[cfg(any(feature = "std", test))] use std::{fmt::Debug, sync::Arc}; #[cfg(feature = "datasize")] @@ -31,7 +33,7 @@ use tracing::error; use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes}, - ChainNameDigest, Digest, EraId, ProtocolVersion, + ChainNameDigest, Digest, EraId, ProtocolVersion, Timestamp, }; pub use accounts_config::{ AccountConfig, AccountsConfig, AdministratorAccount, DelegatorConfig, GenesisAccount, @@ -39,16 +41,23 @@ pub use accounts_config::{ }; pub use activation_point::ActivationPoint; pub use chainspec_raw_bytes::ChainspecRawBytes; -pub use core_config::{ConsensusProtocolName, CoreConfig, LegacyRequiredFinality}; +#[cfg(any(feature = "testing", test))] +pub use core_config::DEFAULT_FEE_HANDLING; +#[cfg(any(feature = "std", test))] +pub use core_config::DEFAULT_REFUND_HANDLING; +pub use core_config::{ + ConsensusProtocolName, CoreConfig, LegacyRequiredFinality, DEFAULT_BALANCE_HOLD_INTERVAL, +}; pub use fee_handling::FeeHandling; +#[cfg(any(feature = "testing", test))] +pub use genesis_config::DEFAULT_AUCTION_DELAY; #[cfg(any(feature = "std", test))] pub use genesis_config::{GenesisConfig, GenesisConfigBuilder}; -#[cfg(any(feature = "testing", test))] -pub use genesis_config::{DEFAULT_AUCTION_DELAY, DEFAULT_FEE_HANDLING, DEFAULT_REFUND_HANDLING}; pub use global_state_update::{GlobalStateUpdate, GlobalStateUpdateConfig, GlobalStateUpdateError}; pub use highway_config::HighwayConfig; pub use network_config::NetworkConfig; pub use next_upgrade::NextUpgrade; +pub use pricing_handling::PricingHandling; pub use protocol_config::ProtocolConfig; pub use refund_handling::RefundHandling; pub use transaction_config::{DeployConfig, TransactionConfig, TransactionV1Config}; @@ -190,6 +199,14 @@ impl Chainspec { fee_handling, )) } + + /// Returns balance hold epoch based upon configured hold interval, calculated from the imputed + /// timestamp. + pub fn balance_holds_epoch(&self, timestamp: Timestamp) -> u64 { + timestamp + .millis() + .saturating_sub(self.core_config.balance_hold_interval.millis()) + } } #[cfg(any(feature = "testing", test))] @@ -202,7 +219,7 @@ impl Chainspec { let highway_config = HighwayConfig::random(rng); let transaction_config = TransactionConfig::random(rng); let wasm_config = rng.gen(); - let system_costs_config = rng.gen(); + let system_costs_config = SystemConfig::random(rng); let vacancy_config = VacancyConfig::random(rng); Chainspec { @@ -216,6 +233,30 @@ impl Chainspec { vacancy_config, } } + + /// Set the chain name; + pub fn with_chain_name(&mut self, chain_name: String) -> &mut Self { + self.network_config.name = chain_name; + self + } + + /// Set max associated keys. + pub fn with_max_associated_keys(&mut self, max_associated_keys: u32) -> &mut Self { + self.core_config.max_associated_keys = max_associated_keys; + self + } + + /// Set pricing handling. + pub fn with_pricing_handling(&mut self, pricing_handling: PricingHandling) -> &mut Self { + self.core_config.pricing_handling = pricing_handling; + self + } + + /// Set allow reservations. + pub fn with_allow_reservations(&mut self, allow_reservations: bool) -> &mut Self { + self.core_config.allow_reservations = allow_reservations; + self + } } impl ToBytes for Chainspec { diff --git a/types/src/chainspec/accounts_config.rs b/types/src/chainspec/accounts_config.rs index 1b820eb5ff..e5e3fb278a 100644 --- a/types/src/chainspec/accounts_config.rs +++ b/types/src/chainspec/accounts_config.rs @@ -102,7 +102,7 @@ impl AccountsConfig { pub fn random(rng: &mut TestRng) -> Self { use rand::Rng; - use crate::{Motes, U512}; + use crate::Motes; let alpha = AccountConfig::random(rng); let accounts = vec![ @@ -120,7 +120,7 @@ impl AccountsConfig { let admin_balance: u32 = rng.gen(); let administrators = vec![AdministratorAccount::new( PublicKey::random(rng), - Motes::new(U512::from(admin_balance)), + Motes::new(admin_balance), )]; AccountsConfig { diff --git a/types/src/chainspec/accounts_config/account_config.rs b/types/src/chainspec/accounts_config/account_config.rs index 7c998d355c..b64cb97efb 100644 --- a/types/src/chainspec/accounts_config/account_config.rs +++ b/types/src/chainspec/accounts_config/account_config.rs @@ -1,6 +1,5 @@ #[cfg(feature = "datasize")] use datasize::DataSize; -use num::Zero; #[cfg(any(feature = "testing", test))] use rand::{distributions::Standard, prelude::*}; @@ -69,7 +68,7 @@ impl AccountConfig { pub fn random(rng: &mut TestRng) -> Self { let public_key = PublicKey::from(&SecretKey::ed25519_from_bytes(rng.gen::<[u8; 32]>()).unwrap()); - let balance = Motes::new(rng.gen()); + let balance = Motes::new(rng.gen::()); let validator = rng.gen(); AccountConfig { diff --git a/types/src/chainspec/accounts_config/delegator_config.rs b/types/src/chainspec/accounts_config/delegator_config.rs index b91422b5c1..f6fa63afc3 100644 --- a/types/src/chainspec/accounts_config/delegator_config.rs +++ b/types/src/chainspec/accounts_config/delegator_config.rs @@ -50,8 +50,8 @@ impl DelegatorConfig { PublicKey::from(&SecretKey::ed25519_from_bytes(rng.gen::<[u8; 32]>()).unwrap()); let delegator_public_key = PublicKey::from(&SecretKey::ed25519_from_bytes(rng.gen::<[u8; 32]>()).unwrap()); - let balance = Motes::new(U512::from(rng.gen::())); - let delegated_amount = Motes::new(U512::from(rng.gen::())); + let balance = Motes::new(rng.gen::()); + let delegated_amount = Motes::new(rng.gen::()); DelegatorConfig { validator_public_key, diff --git a/types/src/chainspec/accounts_config/genesis.rs b/types/src/chainspec/accounts_config/genesis.rs index dae8d3fe18..8691578f93 100644 --- a/types/src/chainspec/accounts_config/genesis.rs +++ b/types/src/chainspec/accounts_config/genesis.rs @@ -1,6 +1,5 @@ #[cfg(feature = "datasize")] use datasize::DataSize; -use num_traits::Zero; #[cfg(any(feature = "testing", test))] use rand::{ distributions::{Distribution, Standard}, @@ -86,7 +85,7 @@ impl GenesisValidator { #[cfg(any(feature = "testing", test))] impl Distribution for Standard { fn sample(&self, rng: &mut R) -> GenesisValidator { - let bonded_amount = Motes::new(rng.gen()); + let bonded_amount = Motes::new(rng.gen::()); let delegation_rate = rng.gen(); GenesisValidator::new(bonded_amount, delegation_rate) @@ -386,7 +385,7 @@ impl Distribution for Standard { rng.fill_bytes(&mut bytes[..]); let secret_key = SecretKey::ed25519_from_bytes(bytes).unwrap(); let public_key = PublicKey::from(&secret_key); - let balance = Motes::new(rng.gen()); + let balance = Motes::new(rng.gen::()); let validator = rng.gen(); GenesisAccount::account(public_key, balance, validator) @@ -419,8 +418,8 @@ impl ToBytes for GenesisAccount { buffer.push(GenesisAccountTag::Delegator as u8); buffer.extend(validator_public_key.to_bytes()?); buffer.extend(delegator_public_key.to_bytes()?); - buffer.extend(balance.value().to_bytes()?); - buffer.extend(delegated_amount.value().to_bytes()?); + buffer.extend(balance.to_bytes()?); + buffer.extend(delegated_amount.to_bytes()?); } GenesisAccount::Administrator(administrator_account) => { buffer.push(GenesisAccountTag::Administrator as u8); @@ -486,7 +485,7 @@ impl FromBytes for GenesisAccount { validator_public_key, delegator_public_key, balance, - Motes::new(delegated_amount_value), + delegated_amount_value, ); Ok((genesis_account, remainder)) } diff --git a/types/src/chainspec/accounts_config/validator_config.rs b/types/src/chainspec/accounts_config/validator_config.rs index 588faa49ee..6b308b7c37 100644 --- a/types/src/chainspec/accounts_config/validator_config.rs +++ b/types/src/chainspec/accounts_config/validator_config.rs @@ -44,7 +44,7 @@ impl ValidatorConfig { /// Returns a random `ValidatorConfig`. #[cfg(any(feature = "testing", test))] pub fn random(rng: &mut TestRng) -> Self { - let bonded_amount = Motes::new(U512::from(rng.gen::())); + let bonded_amount = Motes::new(rng.gen::()); let delegation_rate = rng.gen(); ValidatorConfig { diff --git a/types/src/chainspec/core_config.rs b/types/src/chainspec/core_config.rs index 6b3c12f660..946d70a397 100644 --- a/types/src/chainspec/core_config.rs +++ b/types/src/chainspec/core_config.rs @@ -20,7 +20,9 @@ use crate::{ ProtocolVersion, PublicKey, TimeDiff, }; -use super::{fee_handling::FeeHandling, refund_handling::RefundHandling}; +use super::{ + fee_handling::FeeHandling, pricing_handling::PricingHandling, refund_handling::RefundHandling, +}; /// Default value for maximum associated keys configuration option. pub const DEFAULT_MAX_ASSOCIATED_KEYS: u32 = 100; @@ -28,6 +30,21 @@ pub const DEFAULT_MAX_ASSOCIATED_KEYS: u32 = 100; /// Default value for maximum runtime call stack height configuration option. pub const DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT: u32 = 12; +/// Default refund handling. +pub const DEFAULT_REFUND_HANDLING: RefundHandling = RefundHandling::NoRefund; + +/// Default pricing handling. +pub const DEFAULT_PRICING_HANDLING: PricingHandling = PricingHandling::Fixed; + +/// Default fee handling. +pub const DEFAULT_FEE_HANDLING: FeeHandling = FeeHandling::NoFee; + +/// Default allow reservations. +pub const DEFAULT_ALLOW_RESERVATIONS: bool = false; + +/// Default balance hold interval. +pub const DEFAULT_BALANCE_HOLD_INTERVAL: TimeDiff = TimeDiff::from_seconds(24 * 60 * 60); + /// Configuration values associated with the core protocol. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "datasize", derive(DataSize))] @@ -120,14 +137,20 @@ pub struct CoreConfig { pub allow_unrestricted_transfers: bool, /// If set to false then consensus doesn't compute rewards and always uses 0. pub compute_rewards: bool, - /// Administrative accounts are a valid option for a private chain only. - #[serde(default, skip_serializing_if = "BTreeSet::is_empty")] - pub administrators: BTreeSet, /// Refund handling. #[cfg_attr(feature = "datasize", data_size(skip))] pub refund_handling: RefundHandling, /// Fee handling. pub fee_handling: FeeHandling, + /// Pricing handling. + pub pricing_handling: PricingHandling, + /// Allow reservations. + pub allow_reservations: bool, + /// How long does it take for a balance hold to fade away? + pub balance_hold_interval: TimeDiff, + /// Administrative accounts are a valid option for a private chain only. + //#[serde(default, skip_serializing_if = "BTreeSet::is_empty")] + pub administrators: BTreeSet, } impl CoreConfig { @@ -196,12 +219,22 @@ impl CoreConfig { RefundHandling::Refund { refund_ratio } }; + let pricing_handling = if rng.gen() { + PricingHandling::Classic + } else { + PricingHandling::Fixed + }; + + let allow_reservations = DEFAULT_ALLOW_RESERVATIONS; + let fee_handling = if rng.gen() { FeeHandling::PayToProposer } else { - FeeHandling::Accumulate + FeeHandling::NoFee }; + let balance_hold_interval = TimeDiff::from_seconds(rng.gen_range(600..604_800)); + CoreConfig { era_duration, minimum_era_height, @@ -231,7 +264,10 @@ impl CoreConfig { allow_unrestricted_transfers, compute_rewards, refund_handling, + pricing_handling, + allow_reservations, fee_handling, + balance_hold_interval, } } } @@ -267,10 +303,11 @@ impl Default for CoreConfig { allow_unrestricted_transfers: true, compute_rewards: true, administrators: Default::default(), - refund_handling: RefundHandling::Refund { - refund_ratio: Ratio::new_raw(99, 100), - }, - fee_handling: FeeHandling::PayToProposer, + refund_handling: DEFAULT_REFUND_HANDLING, + pricing_handling: DEFAULT_PRICING_HANDLING, + fee_handling: DEFAULT_FEE_HANDLING, + allow_reservations: DEFAULT_ALLOW_RESERVATIONS, + balance_hold_interval: DEFAULT_BALANCE_HOLD_INTERVAL, } } } @@ -309,7 +346,10 @@ impl ToBytes for CoreConfig { buffer.extend(self.compute_rewards.to_bytes()?); buffer.extend(self.administrators.to_bytes()?); buffer.extend(self.refund_handling.to_bytes()?); + buffer.extend(self.pricing_handling.to_bytes()?); buffer.extend(self.fee_handling.to_bytes()?); + buffer.extend(self.allow_reservations.to_bytes()?); + buffer.extend(self.balance_hold_interval.to_bytes()?); Ok(buffer) } @@ -344,7 +384,10 @@ impl ToBytes for CoreConfig { + self.compute_rewards.serialized_length() + self.administrators.serialized_length() + self.refund_handling.serialized_length() + + self.pricing_handling.serialized_length() + self.fee_handling.serialized_length() + + self.allow_reservations.serialized_length() + + self.balance_hold_interval.serialized_length() } } @@ -379,7 +422,10 @@ impl FromBytes for CoreConfig { let (compute_rewards, remainder) = bool::from_bytes(remainder)?; let (administrative_accounts, remainder) = FromBytes::from_bytes(remainder)?; let (refund_handling, remainder) = FromBytes::from_bytes(remainder)?; + let (pricing_handling, remainder) = FromBytes::from_bytes(remainder)?; let (fee_handling, remainder) = FromBytes::from_bytes(remainder)?; + let (allow_reservations, remainder) = FromBytes::from_bytes(remainder)?; + let (balance_hold_interval, remainder) = TimeDiff::from_bytes(remainder)?; let config = CoreConfig { era_duration, minimum_era_height, @@ -409,7 +455,10 @@ impl FromBytes for CoreConfig { compute_rewards, administrators: administrative_accounts, refund_handling, + pricing_handling, fee_handling, + allow_reservations, + balance_hold_interval, }; Ok((config, remainder)) } diff --git a/types/src/chainspec/fee_handling.rs b/types/src/chainspec/fee_handling.rs index 199d956c61..4ec10ca64a 100644 --- a/types/src/chainspec/fee_handling.rs +++ b/types/src/chainspec/fee_handling.rs @@ -26,7 +26,7 @@ pub enum FeeHandling { /// Burn the fees. Burn, /// No fees. - None, + NoFee, } impl FeeHandling { @@ -34,6 +34,11 @@ impl FeeHandling { pub fn is_accumulate(&self) -> bool { matches!(self, FeeHandling::Accumulate) } + + /// Returns true if configured for no fees. + pub fn skip_fee_handling(&self) -> bool { + matches!(self, FeeHandling::NoFee) + } } impl ToBytes for FeeHandling { @@ -42,7 +47,7 @@ impl ToBytes for FeeHandling { FeeHandling::PayToProposer => Ok(vec![FEE_HANDLING_PROPOSER_TAG]), FeeHandling::Accumulate => Ok(vec![FEE_HANDLING_ACCUMULATE_TAG]), FeeHandling::Burn => Ok(vec![FEE_HANDLING_BURN_TAG]), - FeeHandling::None => Ok(vec![FEE_HANDLING_NONE_TAG]), + FeeHandling::NoFee => Ok(vec![FEE_HANDLING_NONE_TAG]), } } @@ -58,7 +63,7 @@ impl FromBytes for FeeHandling { FEE_HANDLING_PROPOSER_TAG => Ok((FeeHandling::PayToProposer, rem)), FEE_HANDLING_ACCUMULATE_TAG => Ok((FeeHandling::Accumulate, rem)), FEE_HANDLING_BURN_TAG => Ok((FeeHandling::Burn, rem)), - FEE_HANDLING_NONE_TAG => Ok((FeeHandling::None, rem)), + FEE_HANDLING_NONE_TAG => Ok((FeeHandling::NoFee, rem)), _ => Err(bytesrepr::Error::Formatting), } } @@ -66,10 +71,10 @@ impl FromBytes for FeeHandling { impl Default for FeeHandling { fn default() -> Self { - // in 2.x the default is None as there are no fees. - // FeeHandling::None // in 1.x the (implicit) default was PayToProposer - FeeHandling::PayToProposer + // FeeHandling::PayToProposer + // in 2.x the default is NoFee as there are no fees. + FeeHandling::NoFee } } @@ -94,4 +99,10 @@ mod tests { let fee_config = FeeHandling::Burn; bytesrepr::test_serialization_roundtrip(&fee_config); } + + #[test] + fn bytesrepr_roundtrip_for_no_fee() { + let fee_config = FeeHandling::NoFee; + bytesrepr::test_serialization_roundtrip(&fee_config); + } } diff --git a/types/src/chainspec/genesis_config.rs b/types/src/chainspec/genesis_config.rs index 9890474faa..480e35c1fa 100644 --- a/types/src/chainspec/genesis_config.rs +++ b/types/src/chainspec/genesis_config.rs @@ -1,3 +1,5 @@ +//! Contains genesis configuration settings. + #[cfg(any(feature = "testing", test))] use std::iter; @@ -10,8 +12,7 @@ use rand::{ use serde::{Deserialize, Serialize}; use crate::{ - AdministratorAccount, Chainspec, FeeHandling, GenesisAccount, Motes, PublicKey, RefundHandling, - SystemConfig, WasmConfig, + AdministratorAccount, Chainspec, GenesisAccount, Motes, PublicKey, SystemConfig, WasmConfig, }; /// Default number of validator slots. @@ -32,12 +33,6 @@ pub const DEFAULT_UNBONDING_DELAY: u64 = 7; pub const DEFAULT_ROUND_SEIGNIORAGE_RATE: Ratio = Ratio::new_raw(7, 175070816); /// Default genesis timestamp in milliseconds. pub const DEFAULT_GENESIS_TIMESTAMP_MILLIS: u64 = 0; -/// Default fee handling. -pub const DEFAULT_FEE_HANDLING: FeeHandling = FeeHandling::PayToProposer; -/// Default gas cost refund ratio. -pub const DEFAULT_REFUND_HANDLING: RefundHandling = RefundHandling::Refund { - refund_ratio: Ratio::new_raw(99, 100), -}; /// Represents the details of a genesis process. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -51,8 +46,6 @@ pub struct GenesisConfig { round_seigniorage_rate: Ratio, unbonding_delay: u64, genesis_timestamp_millis: u64, - refund_handling: RefundHandling, - fee_handling: FeeHandling, } impl GenesisConfig { @@ -86,8 +79,6 @@ impl GenesisConfig { round_seigniorage_rate, unbonding_delay, genesis_timestamp_millis, - refund_handling: DEFAULT_REFUND_HANDLING, - fee_handling: DEFAULT_FEE_HANDLING, } } @@ -195,16 +186,6 @@ impl Distribution for Standard { let genesis_timestamp_millis = rng.gen(); - let refund_handling = RefundHandling::Refund { - refund_ratio: Ratio::new_raw(rng.gen_range(0..=100), 100), - }; - - let fee_handling = if rng.gen() { - FeeHandling::Accumulate - } else { - FeeHandling::PayToProposer - }; - GenesisConfig { accounts, wasm_config, @@ -215,8 +196,6 @@ impl Distribution for Standard { round_seigniorage_rate, unbonding_delay, genesis_timestamp_millis, - refund_handling, - fee_handling, } } } @@ -236,8 +215,6 @@ pub struct GenesisConfigBuilder { round_seigniorage_rate: Option>, unbonding_delay: Option, genesis_timestamp_millis: Option, - refund_handling: Option, - fee_handling: Option, } impl GenesisConfigBuilder { @@ -300,18 +277,6 @@ impl GenesisConfigBuilder { self } - /// Sets the refund handling config option. - pub fn with_refund_handling(mut self, refund_handling: RefundHandling) -> Self { - self.refund_handling = Some(refund_handling); - self - } - - /// Sets the fee handling config option. - pub fn with_fee_handling(mut self, fee_handling: FeeHandling) -> Self { - self.fee_handling = Some(fee_handling); - self - } - /// Builds a new [`GenesisConfig`] object. pub fn build(self) -> GenesisConfig { GenesisConfig { @@ -330,8 +295,6 @@ impl GenesisConfigBuilder { genesis_timestamp_millis: self .genesis_timestamp_millis .unwrap_or(DEFAULT_GENESIS_TIMESTAMP_MILLIS), - refund_handling: self.refund_handling.unwrap_or(DEFAULT_REFUND_HANDLING), - fee_handling: self.fee_handling.unwrap_or(DEFAULT_FEE_HANDLING), } } } @@ -354,8 +317,6 @@ impl From<&Chainspec> for GenesisConfig { .with_round_seigniorage_rate(chainspec.core_config.round_seigniorage_rate) .with_unbonding_delay(chainspec.core_config.unbonding_delay) .with_genesis_timestamp_millis(genesis_timestamp_millis) - .with_refund_handling(chainspec.core_config.refund_handling) - .with_fee_handling(chainspec.core_config.fee_handling) .build() } } diff --git a/types/src/chainspec/next_upgrade.rs b/types/src/chainspec/next_upgrade.rs index 897755f9db..8bb645265e 100644 --- a/types/src/chainspec/next_upgrade.rs +++ b/types/src/chainspec/next_upgrade.rs @@ -11,10 +11,10 @@ use crate::{ ActivationPoint, ProtocolConfig, ProtocolVersion, }; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use rand::Rng; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; /// Information about the next protocol upgrade. @@ -40,8 +40,9 @@ impl NextUpgrade { self.activation_point } - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { Self { activation_point: ActivationPoint::random(rng), protocol_version: ProtocolVersion::from_parts(rng.gen(), rng.gen(), rng.gen()), diff --git a/types/src/chainspec/pricing_handling.rs b/types/src/chainspec/pricing_handling.rs new file mode 100644 index 0000000000..e7c934daf9 --- /dev/null +++ b/types/src/chainspec/pricing_handling.rs @@ -0,0 +1,95 @@ +use crate::{ + bytesrepr, + bytesrepr::{FromBytes, ToBytes}, +}; +use core::fmt::{Display, Formatter}; +#[cfg(feature = "datasize")] +use datasize::DataSize; +use serde::{Deserialize, Serialize}; + +const PRICING_HANDLING_CLASSIC_TAG: u8 = 0; +const PRICING_HANDLING_FIXED_TAG: u8 = 1; + +const PRICING_HANDLING_TAG_LENGTH: u8 = 1; + +/// Defines what pricing mode a network allows. Correlates to the PricingMode of a +/// [`crate::Transaction`]. Nodes will not accept transactions whose pricing mode does not match. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[cfg_attr(feature = "datasize", derive(DataSize))] +pub enum PricingHandling { + /// The transaction sender self-specifies how much token they pay, which becomes their gas + /// limit. + Classic, + /// The costs are fixed, per the cost tables. + Fixed, +} + +impl Display for PricingHandling { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + PricingHandling::Classic => { + write!(f, "PricingHandling::Classic") + } + PricingHandling::Fixed => { + write!(f, "PricingHandling::Fixed") + } + } + } +} + +impl ToBytes for PricingHandling { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buffer = bytesrepr::allocate_buffer(self)?; + + match self { + PricingHandling::Classic => { + buffer.push(PRICING_HANDLING_CLASSIC_TAG); + } + PricingHandling::Fixed => { + buffer.push(PRICING_HANDLING_FIXED_TAG); + } + } + + Ok(buffer) + } + + fn serialized_length(&self) -> usize { + PRICING_HANDLING_TAG_LENGTH as usize + } +} + +impl FromBytes for PricingHandling { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (tag, rem) = u8::from_bytes(bytes)?; + match tag { + PRICING_HANDLING_CLASSIC_TAG => Ok((PricingHandling::Classic, rem)), + PRICING_HANDLING_FIXED_TAG => Ok((PricingHandling::Fixed, rem)), + _ => Err(bytesrepr::Error::Formatting), + } + } +} + +impl Default for PricingHandling { + fn default() -> Self { + // in 2.0 the default pricing handling is Fixed + PricingHandling::Fixed + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bytesrepr_roundtrip_for_classic() { + let handling = PricingHandling::Classic; + bytesrepr::test_serialization_roundtrip(&handling); + } + + #[test] + fn bytesrepr_roundtrip_for_fixed() { + let handling = PricingHandling::Fixed; + bytesrepr::test_serialization_roundtrip(&handling); + } +} diff --git a/types/src/chainspec/protocol_config.rs b/types/src/chainspec/protocol_config.rs index 421c68c4d2..5d4aecf719 100644 --- a/types/src/chainspec/protocol_config.rs +++ b/types/src/chainspec/protocol_config.rs @@ -9,13 +9,13 @@ use std::{collections::BTreeMap, str::FromStr}; use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes}, - Key, ProtocolVersion, StoredValue, + Key, ProtocolVersion, StoredValue, Timestamp, }; use crate::{ActivationPoint, GlobalStateUpdate}; /// Configuration values associated with the protocol. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "datasize", derive(DataSize))] pub struct ProtocolConfig { /// Protocol version. @@ -104,6 +104,17 @@ impl FromBytes for ProtocolConfig { } } +impl Default for ProtocolConfig { + fn default() -> Self { + ProtocolConfig { + activation_point: ActivationPoint::Genesis(Timestamp::now()), + global_state_update: None, + hard_reset: true, + version: ProtocolVersion::V2_0_0, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/types/src/chainspec/refund_handling.rs b/types/src/chainspec/refund_handling.rs index 0bda9edbd1..56e2a0831f 100644 --- a/types/src/chainspec/refund_handling.rs +++ b/types/src/chainspec/refund_handling.rs @@ -1,6 +1,7 @@ /// Configuration options of refund handling that are executed as part of handle payment /// finalization. use num_rational::Ratio; +use num_traits::Zero; use serde::{Deserialize, Serialize}; use crate::bytesrepr::{self, FromBytes, ToBytes}; @@ -32,7 +33,18 @@ pub enum RefundHandling { refund_ratio: Ratio, }, /// No refunds. - None, + NoRefund, +} + +impl RefundHandling { + /// Returns true if we don't need to process a refund. + pub fn skip_refund(&self) -> bool { + match self { + RefundHandling::NoRefund => true, + RefundHandling::Refund { refund_ratio } => refund_ratio.is_zero(), + RefundHandling::Burn { .. } => false, + } + } } impl ToBytes for RefundHandling { @@ -48,7 +60,7 @@ impl ToBytes for RefundHandling { buffer.push(REFUND_HANDLING_BURN_TAG); buffer.extend(refund_ratio.to_bytes()?); } - RefundHandling::None => { + RefundHandling::NoRefund => { buffer.push(REFUND_HANDLING_NONE_TAG); } } @@ -60,7 +72,7 @@ impl ToBytes for RefundHandling { 1 + match self { RefundHandling::Refund { refund_ratio } => refund_ratio.serialized_length(), RefundHandling::Burn { refund_ratio } => refund_ratio.serialized_length(), - RefundHandling::None => 0, + RefundHandling::NoRefund => 0, } } } @@ -77,7 +89,7 @@ impl FromBytes for RefundHandling { let (refund_ratio, rem) = FromBytes::from_bytes(rem)?; Ok((RefundHandling::Burn { refund_ratio }, rem)) } - REFUND_HANDLING_NONE_TAG => Ok((RefundHandling::None, rem)), + REFUND_HANDLING_NONE_TAG => Ok((RefundHandling::NoRefund, rem)), _ => Err(bytesrepr::Error::Formatting), } } @@ -85,13 +97,13 @@ impl FromBytes for RefundHandling { impl Default for RefundHandling { fn default() -> Self { + // in 1.x the default was Refund + // RefundHandling::Refund { + // refund_ratio: Ratio::new(99, 100), + // } // in 2.0 the default payment mode is Fixed with Fee Elimination on, // thus there is nothing to refund. - // RefundHandling::None - // in 1.x the default was Refund - RefundHandling::Refund { - refund_ratio: Ratio::new(99, 100), - } + RefundHandling::NoRefund } } @@ -114,4 +126,10 @@ mod tests { }; bytesrepr::test_serialization_roundtrip(&refund_config); } + + #[test] + fn bytesrepr_roundtrip_for_no_refund() { + let refund_config = RefundHandling::NoRefund; + bytesrepr::test_serialization_roundtrip(&refund_config); + } } diff --git a/types/src/chainspec/transaction_config.rs b/types/src/chainspec/transaction_config.rs index 8382809982..1c0b2a1ff9 100644 --- a/types/src/chainspec/transaction_config.rs +++ b/types/src/chainspec/transaction_config.rs @@ -47,8 +47,6 @@ pub struct TransactionConfig { pub max_block_size: u32, /// Maximum sum of payment across all transactions included in a block. pub block_gas_limit: u64, - /// Chainspec configured cost for native transfers. - pub native_transfer_cost: u32, /// Minimum token amount for a native transfer deploy or transaction (a transfer deploy or /// transaction received with an transfer amount less than this will be rejected upon receipt). pub native_transfer_minimum_motes: u64, @@ -76,7 +74,6 @@ impl TransactionConfig { let block_max_approval_count = rng.gen(); let max_block_size = rng.gen_range(1_000_000..1_000_000_000); let block_gas_limit = rng.gen_range(100_000_000_000..1_000_000_000_000_000); - let native_transfer_cost = 2_500_000_000; let native_transfer_minimum_motes = rng.gen_range(DEFAULT_MIN_TRANSFER_MOTES..1_000_000_000_000_000); let max_timestamp_leeway = TimeDiff::from_seconds(rng.gen_range(0..6)); @@ -93,7 +90,6 @@ impl TransactionConfig { block_max_approval_count, max_block_size, block_gas_limit, - native_transfer_cost, native_transfer_minimum_motes, max_timestamp_leeway, deploy_config, @@ -115,7 +111,6 @@ impl Default for TransactionConfig { block_max_approval_count: 2600, max_block_size: 10_485_760, block_gas_limit: 10_000_000_000_000, - native_transfer_cost: 2_500_000_000, native_transfer_minimum_motes: DEFAULT_MIN_TRANSFER_MOTES, max_timestamp_leeway: TimeDiff::from_seconds(5), deploy_config: DeployConfig::default(), @@ -135,7 +130,6 @@ impl ToBytes for TransactionConfig { self.block_max_approval_count.write_bytes(writer)?; self.max_block_size.write_bytes(writer)?; self.block_gas_limit.write_bytes(writer)?; - self.native_transfer_cost.write_bytes(writer)?; self.native_transfer_minimum_motes.write_bytes(writer)?; self.max_timestamp_leeway.write_bytes(writer)?; self.deploy_config.write_bytes(writer)?; @@ -158,7 +152,6 @@ impl ToBytes for TransactionConfig { + self.block_max_approval_count.serialized_length() + self.max_block_size.serialized_length() + self.block_gas_limit.serialized_length() - + self.native_transfer_cost.serialized_length() + self.native_transfer_minimum_motes.serialized_length() + self.max_timestamp_leeway.serialized_length() + self.deploy_config.serialized_length() @@ -177,7 +170,6 @@ impl FromBytes for TransactionConfig { let (block_max_approval_count, remainder) = u32::from_bytes(remainder)?; let (max_block_size, remainder) = u32::from_bytes(remainder)?; let (block_gas_limit, remainder) = u64::from_bytes(remainder)?; - let (native_transfer_cost, remainder) = u32::from_bytes(remainder)?; let (native_transfer_minimum_motes, remainder) = u64::from_bytes(remainder)?; let (max_timestamp_leeway, remainder) = TimeDiff::from_bytes(remainder)?; let (deploy_config, remainder) = DeployConfig::from_bytes(remainder)?; @@ -193,7 +185,6 @@ impl FromBytes for TransactionConfig { block_max_approval_count, max_block_size, block_gas_limit, - native_transfer_cost, native_transfer_minimum_motes, max_timestamp_leeway, deploy_config, diff --git a/types/src/chainspec/transaction_config/deploy_config.rs b/types/src/chainspec/transaction_config/deploy_config.rs index 7d5757c8ab..b1aeadcfdc 100644 --- a/types/src/chainspec/transaction_config/deploy_config.rs +++ b/types/src/chainspec/transaction_config/deploy_config.rs @@ -11,9 +11,6 @@ use crate::{ Motes, }; -#[cfg(any(feature = "std", test))] -use crate::U512; - /// The default maximum number of motes that payment code execution can cost. pub const DEFAULT_MAX_PAYMENT_MOTES: u64 = 2_500_000_000; @@ -37,7 +34,7 @@ pub struct DeployConfig { impl DeployConfig { /// Generates a random instance using a `TestRng`. pub fn random(rng: &mut TestRng) -> Self { - let max_payment_cost = Motes::new(U512::from(rng.gen_range(1_000_000..1_000_000_000))); + let max_payment_cost = Motes::new(rng.gen_range(1_000_000..1_000_000_000)); let max_dependencies = 0; let payment_args_max_length = rng.gen(); let session_args_max_length = rng.gen(); @@ -55,7 +52,7 @@ impl DeployConfig { impl Default for DeployConfig { fn default() -> Self { DeployConfig { - max_payment_cost: Motes::new(U512::from(DEFAULT_MAX_PAYMENT_MOTES)), + max_payment_cost: Motes::new(DEFAULT_MAX_PAYMENT_MOTES), max_dependencies: 0, payment_args_max_length: 1024, session_args_max_length: 1024, diff --git a/types/src/chainspec/vm_config/auction_costs.rs b/types/src/chainspec/vm_config/auction_costs.rs index 03b2199fc0..2a9aebf103 100644 --- a/types/src/chainspec/vm_config/auction_costs.rs +++ b/types/src/chainspec/vm_config/auction_costs.rs @@ -17,13 +17,13 @@ pub const DEFAULT_READ_SEIGNIORAGE_RECIPIENTS_COST: u32 = 10_000; /// Default cost of the `add_bid` auction entry point. pub const DEFAULT_ADD_BID_COST: u32 = 2_500_000_000; /// Default cost of the `withdraw_bid` auction entry point. -pub const DEFAULT_WITHDRAW_BID_COST: u32 = 2_500_000_000; +pub const DEFAULT_WITHDRAW_BID_COST: u32 = DEFAULT_ADD_BID_COST; /// Default cost of the `delegate` auction entry point. -pub const DEFAULT_DELEGATE_COST: u32 = 2_500_000_000; +pub const DEFAULT_DELEGATE_COST: u32 = DEFAULT_ADD_BID_COST; /// Default cost of the `redelegate` auction entry point. -pub const DEFAULT_REDELEGATE_COST: u32 = 2_500_000_000; +pub const DEFAULT_REDELEGATE_COST: u32 = DEFAULT_ADD_BID_COST; /// Default cost of the `undelegate` auction entry point. -pub const DEFAULT_UNDELEGATE_COST: u32 = 2_500_000_000; +pub const DEFAULT_UNDELEGATE_COST: u32 = DEFAULT_ADD_BID_COST; /// Default cost of the `run_auction` auction entry point. pub const DEFAULT_RUN_AUCTION_COST: u32 = 10_000; /// Default cost of the `slash` auction entry point. diff --git a/types/src/chainspec/vm_config/host_function_costs.rs b/types/src/chainspec/vm_config/host_function_costs.rs index 9bfc86bc06..5da6bbe0bb 100644 --- a/types/src/chainspec/vm_config/host_function_costs.rs +++ b/types/src/chainspec/vm_config/host_function_costs.rs @@ -152,10 +152,10 @@ where /// Calculate gas cost for a host function pub fn calculate_gas_cost(&self, weights: T) -> Gas { - let mut gas = Gas::new(self.cost.into()); + let mut gas = Gas::new(self.cost); for (argument, weight) in self.arguments.as_ref().iter().zip(weights.as_ref()) { - let lhs = Gas::new((*argument).into()); - let rhs = Gas::new((*weight).into()); + let lhs = Gas::new(*argument); + let rhs = Gas::new(*weight); gas += lhs * rhs; } gas @@ -1022,7 +1022,7 @@ mod tests { + (ARGUMENT_COSTS[2] * WEIGHTS[2]); assert_eq!( host_function.calculate_gas_cost(WEIGHTS), - Gas::new(expected_cost.into()) + Gas::new(expected_cost) ); } diff --git a/types/src/chainspec/vm_config/system_config.rs b/types/src/chainspec/vm_config/system_config.rs index 139d9f0a1c..d345f2f736 100644 --- a/types/src/chainspec/vm_config/system_config.rs +++ b/types/src/chainspec/vm_config/system_config.rs @@ -1,3 +1,5 @@ +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; #[cfg(feature = "datasize")] use datasize::DataSize; #[cfg(any(feature = "testing", test))] @@ -13,10 +15,10 @@ use crate::{ }; /// Default gas limit of install / upgrade contracts -pub const DEFAULT_INSTALL_UPGRADE_GAS_LIMIT: u32 = 0; // 100_000_000; TODO: reinstate when adding new payment logic +pub const DEFAULT_INSTALL_UPGRADE_GAS_LIMIT: u64 = 3_500_000_000_000; /// Default gas limit of standard transactions -pub const DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT: u32 = 0; // 100_000_000; TODO: reinstate when adding new payment logic +pub const DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT: u64 = 500_000_000_000; /// Definition of costs in the system. /// @@ -27,10 +29,10 @@ pub const DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT: u32 = 0; // 100_000_000; TODO: #[serde(deny_unknown_fields)] pub struct SystemConfig { /// Standard transaction gas limit expressed in gas. - standard_transaction_gas_limit: u32, + standard_transaction_gas_limit: u64, /// Install or upgrade transaction gas limit expressed in gas. - install_upgrade_gas_limit: u32, + install_upgrade_gas_limit: u64, /// Configuration of auction entrypoint costs. auction_costs: AuctionCosts, @@ -48,8 +50,8 @@ pub struct SystemConfig { impl SystemConfig { /// Creates new system config instance. pub fn new( - install_upgrade_gas_limit: u32, - standard_transaction_gas_limit: u32, + install_upgrade_gas_limit: u64, + standard_transaction_gas_limit: u64, auction_costs: AuctionCosts, mint_costs: MintCosts, handle_payment_costs: HandlePaymentCosts, @@ -66,12 +68,12 @@ impl SystemConfig { } /// Returns install / upgrade cost. - pub fn install_upgrade_limit(&self) -> u32 { + pub fn install_upgrade_limit(&self) -> u64 { self.install_upgrade_gas_limit } /// Returns standard / flat cost. - pub fn standard_transaction_limit(&self) -> u32 { + pub fn standard_transaction_limit(&self) -> u64 { self.standard_transaction_gas_limit } @@ -102,6 +104,30 @@ impl SystemConfig { } } +#[cfg(any(feature = "testing", test))] +impl SystemConfig { + /// Generates a random instance using a `TestRng`. + pub fn random(rng: &mut TestRng) -> Self { + // there's a bug in toml...under the hood it uses an i64 when it should use a u64 + // this causes flaky test failures if the random result exceeds i64::MAX + let install_upgrade_gas_limit = rng.gen::() as u64; + let standard_transaction_gas_limit = rng.gen::() as u64; + let auction_costs = rng.gen(); + let mint_costs = rng.gen(); + let handle_payment_costs = rng.gen(); + let standard_payment_costs = rng.gen(); + + SystemConfig { + install_upgrade_gas_limit, + standard_transaction_gas_limit, + auction_costs, + mint_costs, + handle_payment_costs, + standard_payment_costs, + } + } +} + impl Default for SystemConfig { fn default() -> Self { Self { @@ -198,6 +224,8 @@ pub mod gens { handle_payment_costs in handle_payment_costs_arb(), standard_payment_costs in standard_payment_costs_arb(), ) -> SystemConfig { + let install_upgrade_gas_limit = install_upgrade_gas_limit as u64; + let standard_transaction_gas_limit =standard_transaction_gas_limit as u64; SystemConfig { install_upgrade_gas_limit, standard_transaction_gas_limit, diff --git a/types/src/cl_value.rs b/types/src/cl_value.rs index 65a8c05885..5d0e10ec73 100644 --- a/types/src/cl_value.rs +++ b/types/src/cl_value.rs @@ -16,11 +16,11 @@ use crate::{ mod checksum_registry; mod dictionary; mod jsonrepr; -mod system_contract_registry; +mod system_entity_registry; pub use checksum_registry::ChecksumRegistry; pub use dictionary::{handle_stored_dictionary_value, DictionaryValue}; -pub use system_contract_registry::SystemEntityRegistry; +pub use system_entity_registry::SystemEntityRegistry; /// Error while converting a [`CLValue`] into a given type. #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] diff --git a/types/src/cl_value/system_contract_registry.rs b/types/src/cl_value/system_entity_registry.rs similarity index 90% rename from types/src/cl_value/system_contract_registry.rs rename to types/src/cl_value/system_entity_registry.rs index 83fa359a9d..18ab5d3d06 100644 --- a/types/src/cl_value/system_contract_registry.rs +++ b/types/src/cl_value/system_entity_registry.rs @@ -12,12 +12,12 @@ use crate::{ AddressableEntityHash, CLType, CLTyped, }; -/// The system contract registry. +/// The system entity registry. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)] pub struct SystemEntityRegistry(BTreeMap); impl SystemEntityRegistry { - /// Returns a new `SystemContractRegistry`. + /// Returns a new `SystemEntityRegistry`. #[allow(clippy::new_without_default)] // This empty `new()` will be replaced in the future. pub fn new() -> Self { SystemEntityRegistry(BTreeMap::new()) @@ -80,9 +80,9 @@ mod tests { #[test] fn bytesrepr_roundtrip() { - let mut system_contract_registry = SystemEntityRegistry::new(); - system_contract_registry.insert("a".to_string(), AddressableEntityHash::new([9; 32])); - bytesrepr::test_serialization_roundtrip(&system_contract_registry); + let mut system_entity_registry = SystemEntityRegistry::new(); + system_entity_registry.insert("a".to_string(), AddressableEntityHash::new([9; 32])); + bytesrepr::test_serialization_roundtrip(&system_entity_registry); } #[test] diff --git a/types/src/contract_messages.rs b/types/src/contract_messages.rs index a999bd9013..f6822ca09b 100644 --- a/types/src/contract_messages.rs +++ b/types/src/contract_messages.rs @@ -202,13 +202,13 @@ mod tests { #[test] fn serialization_roundtrip() { let topic_addr = MessageAddr::new_topic_addr( - EntityAddr::new_contract_entity_addr([1; KEY_HASH_LENGTH]), + EntityAddr::new_smart_contract([1; KEY_HASH_LENGTH]), [2; TOPIC_NAME_HASH_LENGTH].into(), ); bytesrepr::test_serialization_roundtrip(&topic_addr); let message_addr = MessageAddr::new_message_addr( - EntityAddr::new_contract_entity_addr([1; KEY_HASH_LENGTH]), + EntityAddr::new_smart_contract([1; KEY_HASH_LENGTH]), [2; TOPIC_NAME_HASH_LENGTH].into(), 3, ); diff --git a/types/src/contract_messages/messages.rs b/types/src/contract_messages/messages.rs index 7979a9c382..7bbd4f86a9 100644 --- a/types/src/contract_messages/messages.rs +++ b/types/src/contract_messages/messages.rs @@ -191,7 +191,7 @@ impl FromBytes for MessagePayload { #[cfg_attr(feature = "json-schema", derive(JsonSchema))] pub struct Message { /// The identity of the entity that produced the message. - entity_addr: EntityAddr, + entity_hash: EntityAddr, // TODO: this should be EntityAddr /// The payload of the message. message: MessagePayload, /// The name of the topic on which the message was emitted on. @@ -215,7 +215,7 @@ impl Message { block_index: u64, ) -> Self { Self { - entity_addr: source, + entity_hash: source, message, topic_name, topic_name_hash, @@ -225,8 +225,8 @@ impl Message { } /// Returns a reference to the identity of the entity that produced the message. - pub fn entity_addr(&self) -> &EntityAddr { - &self.entity_addr + pub fn entity_hash(&self) -> &EntityAddr { + &self.entity_hash } /// Returns a reference to the payload of the message. @@ -257,14 +257,14 @@ impl Message { /// Returns a new [`Key::Message`] based on the information in the message. /// This key can be used to query the checksum record for the message in global state. pub fn message_key(&self) -> Key { - Key::message(self.entity_addr, self.topic_name_hash, self.topic_index) + Key::message(self.entity_hash, self.topic_name_hash, self.topic_index) } /// Returns a new [`Key::Message`] based on the information in the message. /// This key can be used to query the control record for the topic of this message in global /// state. pub fn topic_key(&self) -> Key { - Key::message_topic(self.entity_addr, self.topic_name_hash) + Key::message_topic(self.entity_hash, self.topic_name_hash) } /// Returns the checksum of the message. @@ -279,7 +279,7 @@ impl Message { impl ToBytes for Message { fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; - buffer.append(&mut self.entity_addr.to_bytes()?); + buffer.append(&mut self.entity_hash.to_bytes()?); buffer.append(&mut self.message.to_bytes()?); buffer.append(&mut self.topic_name.to_bytes()?); buffer.append(&mut self.topic_name_hash.to_bytes()?); @@ -289,7 +289,7 @@ impl ToBytes for Message { } fn serialized_length(&self) -> usize { - self.entity_addr.serialized_length() + self.entity_hash.serialized_length() + self.message.serialized_length() + self.topic_name.serialized_length() + self.topic_name_hash.serialized_length() @@ -308,7 +308,7 @@ impl FromBytes for Message { let (block_index, rem) = FromBytes::from_bytes(rem)?; Ok(( Message { - entity_addr, + entity_hash: entity_addr, message, topic_name, topic_name_hash, @@ -328,7 +328,7 @@ impl Distribution for Standard { let message = Alphanumeric.sample_string(rng, 64).into(); Message { - entity_addr: rng.gen(), + entity_hash: rng.gen(), message, topic_name, topic_name_hash, @@ -356,7 +356,7 @@ mod tests { bytesrepr::test_serialization_roundtrip(&message_payload); let message = Message::new( - EntityAddr::new_contract_entity_addr([1; KEY_HASH_LENGTH]), + EntityAddr::new_smart_contract([1; KEY_HASH_LENGTH]), message_payload, "test_topic".to_string(), TopicNameHash::new([0x4du8; TOPIC_NAME_HASH_LENGTH]), diff --git a/types/src/contracts.rs b/types/src/contracts.rs index 576bf64300..1f72476990 100644 --- a/types/src/contracts.rs +++ b/types/src/contracts.rs @@ -33,11 +33,6 @@ use crate::{ HashAddr, Key, Package, ProtocolVersion, KEY_HASH_LENGTH, }; -/// Maximum number of distinct user groups. -pub const MAX_GROUPS: u8 = 10; -/// Maximum number of URefs which can be assigned across all user groups. -pub const MAX_TOTAL_UREFS: usize = 100; - const CONTRACT_STRING_PREFIX: &str = "contract-"; const PACKAGE_STRING_PREFIX: &str = "contract-package-"; // We need to support the legacy prefix of "contract-package-wasm". @@ -1094,7 +1089,7 @@ mod tests { vec![], CLType::U32, EntryPointAccess::groups(&["Group 2"]), - EntryPointType::Session, + EntryPointType::Caller, ); ret.insert(entrypoint.name().to_owned(), entrypoint); let entrypoint = EntryPoint::new( @@ -1102,7 +1097,7 @@ mod tests { vec![Parameter::new("Foo", CLType::U32)], CLType::U32, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::Session, + EntryPointType::Caller, ); ret.insert(entrypoint.name().to_owned(), entrypoint); ret diff --git a/types/src/deploy_info.rs b/types/src/deploy_info.rs index faa51e7442..a741cf96fd 100644 --- a/types/src/deploy_info.rs +++ b/types/src/deploy_info.rs @@ -25,7 +25,7 @@ pub struct DeployInfo { schemars(with = "DeployHash", description = "Hex-encoded Deploy hash.") )] pub deploy_hash: DeployHash, - /// Transfers performed by the Deploy. + /// Version 1 transfers performed by the Deploy. pub transfers: Vec, /// Account identifier of the creator of the Deploy. pub from: AccountHash, @@ -104,45 +104,23 @@ impl ToBytes for DeployInfo { } } -/// Generators for a `Deploy` +/// Generators for a `DeployInfo` #[cfg(any(feature = "testing", feature = "gens", test))] pub(crate) mod gens { - use alloc::vec::Vec; - - use proptest::{ - array, - collection::{self, SizeRange}, - prelude::{Arbitrary, Strategy}, - }; + use proptest::{collection, prelude::Strategy}; use crate::{ - account::AccountHash, - gens::{u512_arb, uref_arb}, - DeployHash, DeployInfo, TransferAddr, + gens::{account_hash_arb, u512_arb, uref_arb}, + transaction::gens::deploy_hash_arb, + transfer::gens::transfer_v1_addr_arb, + DeployInfo, }; - pub fn deploy_hash_arb() -> impl Strategy { - array::uniform32(::arbitrary()).prop_map(DeployHash::from_raw) - } - - pub fn transfer_addr_arb() -> impl Strategy { - array::uniform32(::arbitrary()).prop_map(TransferAddr::new) - } - - pub fn transfers_arb(size: impl Into) -> impl Strategy> { - collection::vec(transfer_addr_arb(), size) - } - - pub fn account_hash_arb() -> impl Strategy { - array::uniform32(::arbitrary()).prop_map(AccountHash::new) - } - - /// Creates an arbitrary `Deploy` pub fn deploy_info_arb() -> impl Strategy { let transfers_length_range = 0..5; ( deploy_hash_arb(), - transfers_arb(transfers_length_range), + collection::vec(transfer_v1_addr_arb(), transfers_length_range), account_hash_arb(), uref_arb(), u512_arb(), diff --git a/types/src/digest.rs b/types/src/digest.rs index 0548f300f7..a8c9640502 100644 --- a/types/src/digest.rs +++ b/types/src/digest.rs @@ -250,7 +250,6 @@ impl Digest { /// Returns a new `Digest` directly initialized with the provided bytes; no hashing is done. /// /// This is equivalent to `Digest::from`, but is a const function. - #[cfg(any(feature = "testing", test))] pub const fn from_raw(raw_digest: [u8; Self::LENGTH]) -> Self { Digest(raw_digest) } diff --git a/types/src/execution.rs b/types/src/execution.rs index f1f190ad44..2c57b26d9d 100644 --- a/types/src/execution.rs +++ b/types/src/execution.rs @@ -11,7 +11,7 @@ mod transform_kind; pub use effects::Effects; pub use execution_result::ExecutionResult; pub use execution_result_v1::ExecutionResultV1; -pub use execution_result_v2::ExecutionResultV2; +pub use execution_result_v2::{ExecutionResultV2, PaymentInfo}; pub use transform::TransformV2; pub use transform_error::TransformError; pub use transform_kind::{TransformInstruction, TransformKindV2}; diff --git a/types/src/execution/execution_result_v1.rs b/types/src/execution/execution_result_v1.rs index fc8cf49eeb..febfe874db 100644 --- a/types/src/execution/execution_result_v1.rs +++ b/types/src/execution/execution_result_v1.rs @@ -22,7 +22,7 @@ use crate::{ account::AccountHash, bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, system::auction::{Bid, BidKind, EraInfo, UnbondingPurse, WithdrawPurse}, - CLValue, DeployInfo, Key, Transfer, TransferAddr, U128, U256, U512, + CLValue, DeployInfo, Key, TransferAddr, TransferV1, U128, U256, U512, }; #[derive(FromPrimitive, ToPrimitive, Debug)] @@ -103,7 +103,7 @@ pub enum ExecutionResultV1 { Failure { /// The effect of executing the deploy. effect: ExecutionEffect, - /// A record of Transfers performed while executing the deploy. + /// A record of version 1 Transfers performed while executing the deploy. transfers: Vec, /// The cost of executing the deploy. cost: U512, @@ -465,8 +465,8 @@ pub enum TransformKindV1 { WriteDeployInfo(DeployInfo), /// Writes the given EraInfo to global state. WriteEraInfo(EraInfo), - /// Writes the given Transfer to global state. - WriteTransfer(Transfer), + /// Writes the given version 1 Transfer to global state. + WriteTransfer(TransferV1), /// Writes the given Bid to global state. WriteBid(Box), /// Writes the given Withdraw to global state. @@ -644,7 +644,7 @@ impl FromBytes for TransformKindV1 { Ok((TransformKindV1::WriteEraInfo(era_info), remainder)) } TransformTag::WriteTransfer => { - let (transfer, remainder) = Transfer::from_bytes(remainder)?; + let (transfer, remainder) = TransferV1::from_bytes(remainder)?; Ok((TransformKindV1::WriteTransfer(transfer), remainder)) } TransformTag::AddInt32 => { diff --git a/types/src/execution/execution_result_v2.rs b/types/src/execution/execution_result_v2.rs index 994963ab50..d240cca4ac 100644 --- a/types/src/execution/execution_result_v2.rs +++ b/types/src/execution/execution_result_v2.rs @@ -1,7 +1,7 @@ //! This file provides types to allow conversion from an EE `ExecutionResult` into a similar type //! which can be serialized to a valid binary or JSON representation. //! -//! It is stored as metadata related to a given deploy, and made available to clients via the +//! It is stored as metadata related to a given transaction, and made available to clients via the //! JSON-RPC API. #[cfg(any(feature = "testing", test))] @@ -13,7 +13,7 @@ use datasize::DataSize; #[cfg(feature = "json-schema")] use once_cell::sync::Lazy; #[cfg(any(feature = "testing", test))] -use rand::{distributions::Standard, prelude::Distribution, Rng}; +use rand::Rng; #[cfg(feature = "json-schema")] use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -23,12 +23,12 @@ use super::Effects; use super::{TransformKindV2, TransformV2}; #[cfg(any(feature = "testing", test))] use crate::testing::TestRng; +#[cfg(feature = "json-schema")] +use crate::Key; use crate::{ - bytesrepr::{self, FromBytes, ToBytes, RESULT_ERR_TAG, RESULT_OK_TAG, U8_SERIALIZED_LENGTH}, - TransferAddr, U512, + bytesrepr::{self, FromBytes, ToBytes}, + Gas, InitiatorAddr, Transfer, URef, U512, }; -#[cfg(feature = "json-schema")] -use crate::{Key, KEY_HASH_LENGTH}; #[cfg(feature = "json-schema")] static EXECUTION_RESULT: Lazy = Lazy::new(|| { @@ -44,74 +44,79 @@ static EXECUTION_RESULT: Lazy = Lazy::new(|| { effects.push(TransformV2::new(key1, TransformKindV2::AddUInt64(8u64))); effects.push(TransformV2::new(key2, TransformKindV2::Identity)); - let transfers = vec![ - TransferAddr::new([89; KEY_HASH_LENGTH]), - TransferAddr::new([130; KEY_HASH_LENGTH]), - ]; - - ExecutionResultV2::Success { - effects, + let transfers = vec![Transfer::example().clone()]; + + ExecutionResultV2 { + initiator: InitiatorAddr::from(crate::PublicKey::example().clone()), + error_message: None, + limit: Gas::new(123_456), + consumed: Gas::new(100_000), + cost: U512::from(246_912), + payment: vec![PaymentInfo { + source: URef::new([1; crate::UREF_ADDR_LENGTH], crate::AccessRights::READ), + }], transfers, - cost: U512::from(123_456), + effects, } }); -/// The result of executing a single deploy. +/// Breakdown of payments made to cover the cost. #[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] -#[serde(deny_unknown_fields)] -pub enum ExecutionResultV2 { - /// The result of a failed execution. - Failure { - /// The effects of executing the deploy. - effects: Effects, - /// A record of transfers performed while executing the deploy. - transfers: Vec, - /// The cost in Motes of executing the deploy. - cost: U512, - /// The error message associated with executing the deploy. - error_message: String, - }, - /// The result of a successful execution. - Success { - /// The effects of executing the deploy. - effects: Effects, - /// A record of transfers performed while executing the deploy. - transfers: Vec, - /// The cost in Motes of executing the deploy. - cost: U512, - }, +pub struct PaymentInfo { + /// Source purse used for payment of the transaction. + pub source: URef, } -#[cfg(any(feature = "testing", test))] -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> ExecutionResultV2 { - let transfer_count = rng.gen_range(0..6); - let mut transfers = Vec::new(); - for _ in 0..transfer_count { - transfers.push(TransferAddr::new(rng.gen())) - } +impl ToBytes for PaymentInfo { + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.source.write_bytes(writer) + } - let effects = Effects::random(rng); + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buffer = bytesrepr::allocate_buffer(self)?; + self.write_bytes(&mut buffer)?; + Ok(buffer) + } - if rng.gen() { - ExecutionResultV2::Failure { - effects, - transfers, - cost: rng.gen::().into(), - error_message: format!("Error message {}", rng.gen::()), - } - } else { - ExecutionResultV2::Success { - effects, - transfers, - cost: rng.gen::().into(), - } - } + fn serialized_length(&self) -> usize { + self.source.serialized_length() + } +} + +impl FromBytes for PaymentInfo { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (source, remainder) = URef::from_bytes(bytes)?; + Ok((PaymentInfo { source }, remainder)) } } +/// The result of executing a single transaction. +#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] +#[serde(deny_unknown_fields)] +pub struct ExecutionResultV2 { + /// Who initiatied this transaction. + pub initiator: InitiatorAddr, + /// If there is no error message, this execution was processed successfully. + /// If there is an error message, this execution failed to fully process for the stated reason. + pub error_message: Option, + /// What was the maximum allowed gas limit for this transaction?. + pub limit: Gas, + /// How much gas was consumed executing this transaction. + pub consumed: Gas, + /// How much was paid for this transaction. + pub cost: U512, + /// Breakdown of payments made to cover the cost. + pub payment: Vec, + /// A record of transfers performed while executing this transaction. + pub transfers: Vec, + /// The effects of executing this transaction. + pub effects: Effects, +} + impl ExecutionResultV2 { // This method is not intended to be used by third party crates. #[doc(hidden)] @@ -128,54 +133,46 @@ impl ExecutionResultV2 { let transfer_count = rng.gen_range(0..6); let mut transfers = vec![]; for _ in 0..transfer_count { - transfers.push(TransferAddr::new(rng.gen())) + transfers.push(Transfer::random(rng)) } - let cost = U512::from(rng.gen::()); - - if rng.gen() { - ExecutionResultV2::Failure { - effects, - transfers, - cost, - error_message: format!("Error message {}", rng.gen::()), - } - } else { - ExecutionResultV2::Success { - effects, - transfers, - cost, - } + let limit = Gas::new(rng.gen::()); + let gas_price = rng.gen_range(1..6); + // cost = the limit * the price + let cost = limit.value() * U512::from(gas_price); + let range = limit.value().as_u64(); + + // can range from 0 to limit + let consumed = limit - Gas::new(rng.gen_range(0..=range)); + + let payment = vec![PaymentInfo { source: rng.gen() }]; + ExecutionResultV2 { + initiator: InitiatorAddr::random(rng), + effects, + transfers, + cost, + payment, + limit, + consumed, + error_message: if rng.gen() { + Some(format!("Error message {}", rng.gen::())) + } else { + None + }, } } } impl ToBytes for ExecutionResultV2 { fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - match self { - ExecutionResultV2::Failure { - effects, - transfers, - cost, - error_message, - } => { - RESULT_ERR_TAG.write_bytes(writer)?; - effects.write_bytes(writer)?; - transfers.write_bytes(writer)?; - cost.write_bytes(writer)?; - error_message.write_bytes(writer) - } - ExecutionResultV2::Success { - effects, - transfers, - cost, - } => { - RESULT_OK_TAG.write_bytes(writer)?; - effects.write_bytes(writer)?; - transfers.write_bytes(writer)?; - cost.write_bytes(writer) - } - } + self.initiator.write_bytes(writer)?; // initiator should logically be first + self.error_message.write_bytes(writer)?; + self.limit.write_bytes(writer)?; + self.consumed.write_bytes(writer)?; + self.cost.write_bytes(writer)?; + self.payment.write_bytes(writer)?; + self.transfers.write_bytes(writer)?; + self.effects.write_bytes(writer) } fn to_bytes(&self) -> Result, bytesrepr::Error> { @@ -185,62 +182,38 @@ impl ToBytes for ExecutionResultV2 { } fn serialized_length(&self) -> usize { - U8_SERIALIZED_LENGTH - + match self { - ExecutionResultV2::Failure { - effects, - transfers, - cost, - error_message, - } => { - effects.serialized_length() - + transfers.serialized_length() - + cost.serialized_length() - + error_message.serialized_length() - } - ExecutionResultV2::Success { - effects, - transfers, - cost, - } => { - effects.serialized_length() - + transfers.serialized_length() - + cost.serialized_length() - } - } + self.initiator.serialized_length() + + self.error_message.serialized_length() + + self.limit.serialized_length() + + self.consumed.serialized_length() + + self.cost.serialized_length() + + self.payment.serialized_length() + + self.transfers.serialized_length() + + self.effects.serialized_length() } } impl FromBytes for ExecutionResultV2 { fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { - let (tag, remainder) = u8::from_bytes(bytes)?; - match tag { - RESULT_ERR_TAG => { - let (effects, remainder) = Effects::from_bytes(remainder)?; - let (transfers, remainder) = Vec::::from_bytes(remainder)?; - let (cost, remainder) = U512::from_bytes(remainder)?; - let (error_message, remainder) = String::from_bytes(remainder)?; - let execution_result = ExecutionResultV2::Failure { - effects, - transfers, - cost, - error_message, - }; - Ok((execution_result, remainder)) - } - RESULT_OK_TAG => { - let (effects, remainder) = Effects::from_bytes(remainder)?; - let (transfers, remainder) = Vec::::from_bytes(remainder)?; - let (cost, remainder) = U512::from_bytes(remainder)?; - let execution_result = ExecutionResultV2::Success { - effects, - transfers, - cost, - }; - Ok((execution_result, remainder)) - } - _ => Err(bytesrepr::Error::Formatting), - } + let (initiator, remainder) = InitiatorAddr::from_bytes(bytes)?; + let (error_message, remainder) = Option::::from_bytes(remainder)?; + let (limit, remainder) = Gas::from_bytes(remainder)?; + let (consumed, remainder) = Gas::from_bytes(remainder)?; + let (cost, remainder) = U512::from_bytes(remainder)?; + let (payment, remainder) = Vec::::from_bytes(remainder)?; + let (transfers, remainder) = Vec::::from_bytes(remainder)?; + let (effects, remainder) = Effects::from_bytes(remainder)?; + let execution_result = ExecutionResultV2 { + initiator, + error_message, + limit, + consumed, + cost, + payment, + transfers, + effects, + }; + Ok((execution_result, remainder)) } } diff --git a/types/src/execution/transform_kind.rs b/types/src/execution/transform_kind.rs index 45731dbb67..8fd52a042e 100644 --- a/types/src/execution/transform_kind.rs +++ b/types/src/execution/transform_kind.rs @@ -46,7 +46,7 @@ impl From for TransformInstruction { /// Representation of a single transformation occurring during execution. /// -/// Note that all arithmetic variants of [`TransformKind`] are commutative which means that a given +/// Note that all arithmetic variants of `TransformKindV2` are commutative which means that a given /// collection of them can be executed in any order to produce the same end result. #[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "datasize", derive(DataSize))] @@ -123,9 +123,9 @@ impl TransformKindV2 { let found = "ByteCode".to_string(); Err(StoredValueTypeMismatch::new(expected, found).into()) } - StoredValue::Transfer(_) => { + StoredValue::LegacyTransfer(_) => { let expected = "Contract or Account".to_string(); - let found = "Transfer".to_string(); + let found = "LegacyTransfer".to_string(); Err(StoredValueTypeMismatch::new(expected, found).into()) } StoredValue::DeployInfo(_) => { diff --git a/types/src/gas.rs b/types/src/gas.rs index 7689849e5f..de6f7f0a2f 100644 --- a/types/src/gas.rs +++ b/types/src/gas.rs @@ -1,5 +1,6 @@ //! The `gas` module is used for working with Gas including converting to and from Motes. +use alloc::vec::Vec; use core::{ fmt, iter::Sum, @@ -9,19 +10,32 @@ use core::{ #[cfg(feature = "datasize")] use datasize::DataSize; use num::Zero; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{Motes, U512}; +use crate::{ + bytesrepr::{self, FromBytes, ToBytes}, + Motes, U512, +}; /// The `Gas` struct represents a `U512` amount of gas. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +#[derive( + Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, +)] #[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] pub struct Gas(U512); impl Gas { /// Constructs a new `Gas`. - pub fn new(value: U512) -> Self { - Gas(value) + pub fn new>(value: T) -> Self { + Gas(value.into()) + } + + /// Constructs a new `Gas` with value `0`. + pub const fn zero() -> Self { + Gas(U512::zero()) } /// Returns the inner `U512` value. @@ -29,21 +43,22 @@ impl Gas { self.0 } - /// Returns the cost to be charged. - pub fn cost(&self, is_system: bool) -> Self { - if is_system { - return Gas::new(U512::zero()); - } - *self - } - /// Converts the given `motes` to `Gas` by dividing them by `conv_rate`. /// - /// Returns `None` if `conv_rate == 0`. - pub fn from_motes(motes: Motes, conv_rate: u64) -> Option { + /// Returns `None` if `motes_per_unit_of_gas == 0`. + pub fn from_motes(motes: Motes, motes_per_unit_of_gas: u8) -> Option { motes .value() - .checked_div(U512::from(conv_rate)) + .checked_div(U512::from(motes_per_unit_of_gas)) + .map(Self::new) + } + + /// Converts the given `U512` to `Gas` by dividing it by `gas_price`. + /// + /// Returns `None` if `gas_price == 0`. + pub fn from_price(base_amount: U512, gas_price: u8) -> Option { + base_amount + .checked_div(U512::from(gas_price)) .map(Self::new) } @@ -52,12 +67,43 @@ impl Gas { self.0.checked_add(rhs.value()).map(Self::new) } + /// Saturating integer addition. Computes `self + rhs`, returning max if overflow occurred. + pub fn saturating_add(self, rhs: Self) -> Self { + Gas(self.0.saturating_add(rhs.value())) + } + + /// Saturating integer subtraction. Computes `self + rhs`, returning min if overflow occurred. + pub fn saturating_sub(self, rhs: Self) -> Self { + Gas(self.0.saturating_sub(rhs.value())) + } + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. pub fn checked_sub(&self, rhs: Self) -> Option { self.0.checked_sub(rhs.value()).map(Self::new) } } +impl ToBytes for Gas { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + self.0.to_bytes() + } + + fn serialized_length(&self) -> usize { + self.0.serialized_length() + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.0.write_bytes(writer) + } +} + +impl FromBytes for Gas { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (value, remainder) = U512::from_bytes(bytes)?; + Ok((Gas(value), remainder)) + } +} + impl fmt::Display for Gas { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.0) @@ -205,7 +251,7 @@ mod tests { #[test] fn should_be_able_to_default() { let gas = Gas::default(); - let expected_gas = Gas::new(U512::from(0)); + let expected_gas = Gas::zero(); assert_eq!(gas, expected_gas, "should be equal") } @@ -221,18 +267,9 @@ mod tests { assert!(left_gas < right_gas, "should be lt"); } - #[test] - fn should_default() { - let left_gas = Gas::new(U512::from(0)); - let right_gas = Gas::default(); - assert_eq!(left_gas, right_gas, "should be equal"); - let u512 = U512::zero(); - assert_eq!(left_gas.value(), u512, "should be equal"); - } - #[test] fn should_support_checked_div_from_motes() { - let motes = Motes::new(U512::zero()); + let motes = Motes::zero(); let conv_rate = 0; let maybe = Gas::from_motes(motes, conv_rate); assert!(maybe.is_none(), "should be none due to divide by zero"); diff --git a/types/src/gens.rs b/types/src/gens.rs index 5d38bf82ad..6c1572961b 100644 --- a/types/src/gens.rs +++ b/types/src/gens.rs @@ -18,38 +18,41 @@ use proptest::{ }; use crate::{ - account::{self, action_thresholds::gens::account_action_thresholds_arb, AccountHash}, - addressable_entity::{MessageTopics, NamedKeys, Parameters, Weight}, - contract_messages::{MessageChecksum, MessageTopicSummary, TopicNameHash}, - crypto::{self, gens::public_key_arb_no_system}, - global_state::{Pointer, TrieMerkleProof, TrieMerkleProofStep}, - package::{EntityVersionKey, EntityVersions, Groups, PackageStatus}, - system::auction::{ - gens::era_info_arb, DelegationRate, Delegator, UnbondingPurse, WithdrawPurse, - DELEGATION_RATE_DENOMINATOR, + account::{ + self, action_thresholds::gens::account_action_thresholds_arb, + associated_keys::gens::account_associated_keys_arb, Account, AccountHash, }, - transfer::TransferAddr, - AccessRights, AddressableEntity, AddressableEntityHash, BlockTime, ByteCode, CLType, CLValue, - Digest, EntityKind, EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, EraId, Group, - Key, NamedArg, Package, Parameter, Phase, ProtocolVersion, SemVer, StoredValue, URef, U128, - U256, U512, -}; - -use crate::{ - account::{associated_keys::gens::account_associated_keys_arb, Account}, addressable_entity::{ action_thresholds::gens::action_thresholds_arb, associated_keys::gens::associated_keys_arb, - NamedKeyValue, + MessageTopics, NamedKeyValue, NamedKeys, Parameters, Weight, }, byte_code::ByteCodeKind, + contract_messages::{MessageChecksum, MessageTopicSummary, TopicNameHash}, contracts::{ Contract, ContractHash, ContractPackage, ContractPackageStatus, ContractVersionKey, ContractVersions, }, - deploy_info::gens::{deploy_hash_arb, transfer_addr_arb}, - system::auction::{Bid, BidAddr, BidKind, ValidatorBid}, + crypto::{self, gens::public_key_arb_no_system}, + deploy_info::gens::deploy_info_arb, + global_state::{Pointer, TrieMerkleProof, TrieMerkleProofStep}, + package::{EntityVersionKey, EntityVersions, Groups, PackageStatus}, + system::{ + auction::{ + gens::era_info_arb, Bid, BidAddr, BidKind, DelegationRate, Delegator, UnbondingPurse, + ValidatorBid, WithdrawPurse, DELEGATION_RATE_DENOMINATOR, + }, + mint::BalanceHoldAddr, + }, + transaction::gens::deploy_hash_arb, + transfer::{ + gens::{transfer_v1_addr_arb, transfer_v1_arb}, + TransferAddr, + }, + AccessRights, AddressableEntity, AddressableEntityHash, BlockTime, ByteCode, CLType, CLValue, + Digest, EntityKind, EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, EraId, Group, + Key, NamedArg, Package, Parameter, Phase, ProtocolVersion, SemVer, StoredValue, URef, U128, + U256, U512, }; -pub use crate::{deploy_info::gens::deploy_info_arb, transfer::gens::transfer_arb}; pub fn u8_slice_32() -> impl Strategy { collection::vec(any::(), 32).prop_map(|b| { @@ -107,7 +110,7 @@ pub fn key_arb() -> impl Strategy { account_hash_arb().prop_map(Key::Account), u8_slice_32().prop_map(Key::Hash), uref_arb().prop_map(Key::URef), - transfer_addr_arb().prop_map(Key::Transfer), + transfer_v1_addr_arb().prop_map(Key::Transfer), deploy_hash_arb().prop_map(Key::DeployInfo), era_id_arb().prop_map(Key::EraInfo), uref_arb().prop_map(|uref| Key::Balance(uref.addr())), @@ -115,6 +118,7 @@ pub fn key_arb() -> impl Strategy { bid_addr_delegator_arb().prop_map(Key::BidAddr), account_hash_arb().prop_map(Key::Withdraw), u8_slice_32().prop_map(Key::Dictionary), + balance_hold_addr_arb().prop_map(Key::BalanceHold), Just(Key::EraSummary), ] } @@ -143,6 +147,12 @@ pub fn bid_addr_delegator_arb() -> impl Strategy { (x, y).prop_map(BidAddr::new_delegator_addr) } +pub fn balance_hold_addr_arb() -> impl Strategy { + let x = uref_arb().prop_map(|uref| uref.addr()); + let y = any::(); + (x, y).prop_map(|(x, y)| BalanceHoldAddr::new_gas(x, BlockTime::new(y))) +} + pub fn weight_arb() -> impl Strategy { any::().prop_map(Weight::new) } @@ -318,8 +328,8 @@ pub fn entry_point_access_arb() -> impl Strategy { pub fn entry_point_type_arb() -> impl Strategy { prop_oneof![ - Just(EntryPointType::Session), - Just(EntryPointType::AddressableEntity), + Just(EntryPointType::Caller), + Just(EntryPointType::Called), Just(EntryPointType::Factory), ] } @@ -709,7 +719,7 @@ pub fn stored_value_arb() -> impl Strategy { contract_arb().prop_map(StoredValue::Contract), addressable_entity_arb().prop_map(StoredValue::AddressableEntity), package_arb().prop_map(StoredValue::Package), - transfer_arb().prop_map(StoredValue::Transfer), + transfer_v1_arb().prop_map(StoredValue::LegacyTransfer), deploy_info_arb().prop_map(StoredValue::DeployInfo), era_info_arb(1..10).prop_map(StoredValue::EraInfo), unified_bid_arb(0..3).prop_map(StoredValue::BidKind), @@ -719,31 +729,31 @@ pub fn stored_value_arb() -> impl Strategy { unbondings_arb(1..50).prop_map(StoredValue::Unbonding), message_topic_summary_arb().prop_map(StoredValue::MessageTopic), message_summary_arb().prop_map(StoredValue::Message), - named_key_value_arb().prop_map(StoredValue::NamedKey) + named_key_value_arb().prop_map(StoredValue::NamedKey), ] .prop_map(|stored_value| - // The following match statement is here only to make sure - // we don't forget to update the generator when a new variant is added. - match stored_value { - StoredValue::CLValue(_) => stored_value, - StoredValue::Account(_) => stored_value, - StoredValue::ContractWasm(_) => stored_value, - StoredValue::Contract(_) => stored_value, - StoredValue::ContractPackage(_) => stored_value, - StoredValue::Transfer(_) => stored_value, - StoredValue::DeployInfo(_) => stored_value, - StoredValue::EraInfo(_) => stored_value, - StoredValue::Bid(_) => stored_value, - StoredValue::Withdraw(_) => stored_value, - StoredValue::Unbonding(_) => stored_value, - StoredValue::AddressableEntity(_) => stored_value, - StoredValue::BidKind(_) => stored_value, - StoredValue::Package(_) => stored_value, - StoredValue::ByteCode(_) => stored_value, - StoredValue::MessageTopic(_) => stored_value, - StoredValue::Message(_) => stored_value, - StoredValue::NamedKey(_) => stored_value, - }) + // The following match statement is here only to make sure + // we don't forget to update the generator when a new variant is added. + match stored_value { + StoredValue::CLValue(_) => stored_value, + StoredValue::Account(_) => stored_value, + StoredValue::ContractWasm(_) => stored_value, + StoredValue::Contract(_) => stored_value, + StoredValue::ContractPackage(_) => stored_value, + StoredValue::LegacyTransfer(_) => stored_value, + StoredValue::DeployInfo(_) => stored_value, + StoredValue::EraInfo(_) => stored_value, + StoredValue::Bid(_) => stored_value, + StoredValue::Withdraw(_) => stored_value, + StoredValue::Unbonding(_) => stored_value, + StoredValue::AddressableEntity(_) => stored_value, + StoredValue::BidKind(_) => stored_value, + StoredValue::Package(_) => stored_value, + StoredValue::ByteCode(_) => stored_value, + StoredValue::MessageTopic(_) => stored_value, + StoredValue::Message(_) => stored_value, + StoredValue::NamedKey(_) => stored_value, + }) } pub fn blake2b_hash_arb() -> impl Strategy { diff --git a/types/src/global_state/merkle_proof.rs b/types/src/global_state/merkle_proof.rs index 7065db8bcf..211c0945aa 100644 --- a/types/src/global_state/merkle_proof.rs +++ b/types/src/global_state/merkle_proof.rs @@ -14,14 +14,14 @@ const TRIE_MERKLE_PROOF_STEP_EXTENSION_ID: u8 = 1; /// A component of a proof that an entry exists in the Merkle trie. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum TrieMerkleProofStep { - /// Corresponds to Trie::Node + /// Corresponds to a trie node. Node { /// Hole index. hole_index: u8, /// Indexed pointers with hole. indexed_pointers_with_hole: Vec<(u8, Pointer)>, }, - /// Corresponds to Trie::Extension + /// Corresponds to a trie extension. Extension { /// Affix bytes. affix: Bytes, diff --git a/types/src/key.rs b/types/src/key.rs index 4898c9b7ef..03fcb44503 100644 --- a/types/src/key.rs +++ b/types/src/key.rs @@ -12,7 +12,7 @@ use core::{ str::FromStr, }; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; #[cfg(doc)] @@ -31,6 +31,7 @@ use rand::{ #[cfg(feature = "json-schema")] use schemars::JsonSchema; use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Serializer}; +use tracing::warn; use crate::{ account::{AccountHash, ACCOUNT_HASH_LENGTH}, @@ -46,7 +47,10 @@ use crate::{ contract_wasm::ContractWasmHash, contracts::{ContractHash, ContractPackageHash}, package::PackageHash, - system::auction::{BidAddr, BidAddrTag}, + system::{ + auction::{BidAddr, BidAddrTag}, + mint::BalanceHoldAddr, + }, uref::{self, URef, URefAddr, UREF_SERIALIZED_LENGTH}, ByteCodeAddr, DeployHash, Digest, EraId, Tagged, TransferAddr, TransferFromStrError, TRANSFER_ADDR_LENGTH, UREF_ADDR_LENGTH, @@ -54,13 +58,15 @@ use crate::{ const HASH_PREFIX: &str = "hash-"; const DEPLOY_INFO_PREFIX: &str = "deploy-"; +const TRANSFER_PREFIX: &str = "transfer-"; const ERA_INFO_PREFIX: &str = "era-"; const BALANCE_PREFIX: &str = "balance-"; +const BALANCE_HOLD_PREFIX: &str = "balance-hold-"; const BID_PREFIX: &str = "bid-"; const WITHDRAW_PREFIX: &str = "withdraw-"; const DICTIONARY_PREFIX: &str = "dictionary-"; const UNBOND_PREFIX: &str = "unbond-"; -const SYSTEM_CONTRACT_REGISTRY_PREFIX: &str = "system-contract-registry-"; +const SYSTEM_ENTITY_REGISTRY_PREFIX: &str = "system-entity-registry-"; const ERA_SUMMARY_PREFIX: &str = "era-summary-"; const CHAINSPEC_REGISTRY_PREFIX: &str = "chainspec-registry-"; const CHECKSUM_REGISTRY_PREFIX: &str = "checksum-registry-"; @@ -95,7 +101,7 @@ const KEY_BID_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LEN const KEY_WITHDRAW_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH; const KEY_UNBOND_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_HASH_LENGTH; const KEY_DICTIONARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + KEY_DICTIONARY_LENGTH; -const KEY_SYSTEM_CONTRACT_REGISTRY_SERIALIZED_LENGTH: usize = +const KEY_SYSTEM_ENTITY_REGISTRY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len(); const KEY_ERA_SUMMARY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len(); const KEY_BLOCK_MESSAGE_COUNT_SERIALIZED_LENGTH: usize = @@ -106,7 +112,7 @@ const KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + PADDING_BYTES.len(); const KEY_PACKAGE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH + 32; const KEY_MESSAGE_SERIALIZED_LENGTH: usize = KEY_ID_SERIALIZED_LENGTH - + EntityAddr::ENTITY_ADDR_LENGTH + + EntityAddr::LENGTH + TOPIC_NAME_HASH_LENGTH + U8_SERIALIZED_LENGTH + U32_SERIALIZED_LENGTH; @@ -136,7 +142,7 @@ pub enum KeyTag { Bid = 7, Withdraw = 8, Dictionary = 9, - SystemContractRegistry = 10, + SystemEntityRegistry = 10, EraSummary = 11, Unbond = 12, ChainspecRegistry = 13, @@ -148,12 +154,14 @@ pub enum KeyTag { Message = 19, NamedKey = 20, BlockMessageCount = 21, + BalanceHold = 22, } impl KeyTag { - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { - match rng.gen_range(0..22) { + /// Returns a random `KeyTag`. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { + match rng.gen_range(0..=22) { 0 => KeyTag::Account, 1 => KeyTag::Hash, 2 => KeyTag::URef, @@ -164,7 +172,7 @@ impl KeyTag { 7 => KeyTag::Bid, 8 => KeyTag::Withdraw, 9 => KeyTag::Dictionary, - 10 => KeyTag::SystemContractRegistry, + 10 => KeyTag::SystemEntityRegistry, 11 => KeyTag::EraSummary, 12 => KeyTag::Unbond, 13 => KeyTag::ChainspecRegistry, @@ -176,6 +184,7 @@ impl KeyTag { 19 => KeyTag::Message, 20 => KeyTag::NamedKey, 21 => KeyTag::BlockMessageCount, + 22 => KeyTag::BalanceHold, _ => panic!(), } } @@ -194,7 +203,7 @@ impl Display for KeyTag { KeyTag::Bid => write!(f, "Bid"), KeyTag::Withdraw => write!(f, "Withdraw"), KeyTag::Dictionary => write!(f, "Dictionary"), - KeyTag::SystemContractRegistry => write!(f, "SystemContractRegistry"), + KeyTag::SystemEntityRegistry => write!(f, "SystemEntityRegistry"), KeyTag::EraSummary => write!(f, "EraSummary"), KeyTag::Unbond => write!(f, "Unbond"), KeyTag::ChainspecRegistry => write!(f, "ChainspecRegistry"), @@ -206,6 +215,7 @@ impl Display for KeyTag { KeyTag::Message => write!(f, "Message"), KeyTag::NamedKey => write!(f, "NamedKey"), KeyTag::BlockMessageCount => write!(f, "BlockMessageCount"), + KeyTag::BalanceHold => write!(f, "BalanceHold"), } } } @@ -241,7 +251,7 @@ impl FromBytes for KeyTag { tag if tag == KeyTag::Bid as u8 => KeyTag::Bid, tag if tag == KeyTag::Withdraw as u8 => KeyTag::Withdraw, tag if tag == KeyTag::Dictionary as u8 => KeyTag::Dictionary, - tag if tag == KeyTag::SystemContractRegistry as u8 => KeyTag::SystemContractRegistry, + tag if tag == KeyTag::SystemEntityRegistry as u8 => KeyTag::SystemEntityRegistry, tag if tag == KeyTag::EraSummary as u8 => KeyTag::EraSummary, tag if tag == KeyTag::Unbond as u8 => KeyTag::Unbond, tag if tag == KeyTag::ChainspecRegistry as u8 => KeyTag::ChainspecRegistry, @@ -253,6 +263,7 @@ impl FromBytes for KeyTag { tag if tag == KeyTag::Message as u8 => KeyTag::Message, tag if tag == KeyTag::NamedKey as u8 => KeyTag::NamedKey, tag if tag == KeyTag::BlockMessageCount as u8 => KeyTag::BlockMessageCount, + tag if tag == KeyTag::BalanceHold as u8 => KeyTag::BalanceHold, _ => return Err(Error::Formatting), }; Ok((tag, rem)) @@ -272,7 +283,7 @@ pub enum Key { Hash(HashAddr), /// A `Key` which is a [`URef`], under which most types of data can be stored. URef(URef), - /// A `Key` under which a transfer is stored. + /// A `Key` under which a (legacy) transfer is stored. Transfer(TransferAddr), /// A `Key` under which a deploy info is stored. DeployInfo(DeployHash), @@ -287,7 +298,7 @@ pub enum Key { /// A `Key` whose value is derived by hashing a [`URef`] address and arbitrary data, under /// which a dictionary is stored. Dictionary(DictionaryAddr), - /// A `Key` under which system contract hashes are stored. + /// A `Key` under which system entity hashes are stored. SystemEntityRegistry, /// A `Key` under which current era info is stored. EraSummary, @@ -311,6 +322,8 @@ pub enum Key { NamedKey(NamedKeyAddr), /// A `Key` under which the total number of emitted messages in the last block is stored. BlockMessageCount, + /// A `Key` under which a hold on a purse balance is stored. + BalanceHold(BalanceHoldAddr), } #[cfg(feature = "json-schema")] @@ -341,7 +354,7 @@ pub enum FromStrError { Hash(String), /// URef parse error. URef(uref::FromStrError), - /// Transfer parse error. + /// Legacy Transfer parse error. Transfer(TransferFromStrError), /// DeployInfo parse error. DeployInfo(String), @@ -355,8 +368,8 @@ pub enum FromStrError { Withdraw(String), /// Dictionary parse error. Dictionary(String), - /// System contract registry parse error. - SystemContractRegistry(String), + /// System entity registry parse error. + SystemEntityRegistry(String), /// Era summary parse error. EraSummary(String), /// Unbond parse error. @@ -379,6 +392,8 @@ pub enum FromStrError { NamedKey(String), /// BlockMessageCount key parse error. BlockMessageCount(String), + /// Balance hold parse error. + BalanceHold(String), /// Unknown prefix. UnknownPrefix, } @@ -389,12 +404,6 @@ impl From for FromStrError { } } -impl From for FromStrError { - fn from(error: TransferFromStrError) -> Self { - FromStrError::Transfer(error) - } -} - impl From for FromStrError { fn from(error: uref::FromStrError) -> Self { FromStrError::URef(error) @@ -413,7 +422,9 @@ impl Display for FromStrError { FromStrError::Account(error) => write!(f, "account-key from string error: {}", error), FromStrError::Hash(error) => write!(f, "hash-key from string error: {}", error), FromStrError::URef(error) => write!(f, "uref-key from string error: {}", error), - FromStrError::Transfer(error) => write!(f, "transfer-key from string error: {}", error), + FromStrError::Transfer(error) => { + write!(f, "legacy-transfer-key from string error: {}", error) + } FromStrError::DeployInfo(error) => { write!(f, "deploy-info-key from string error: {}", error) } @@ -424,7 +435,7 @@ impl Display for FromStrError { FromStrError::Dictionary(error) => { write!(f, "dictionary-key from string error: {}", error) } - FromStrError::SystemContractRegistry(error) => { + FromStrError::SystemEntityRegistry(error) => { write!( f, "system-contract-registry-key from string error: {}", @@ -460,6 +471,9 @@ impl Display for FromStrError { FromStrError::BlockMessageCount(error) => { write!(f, "block-message-count-key form string error: {}", error) } + FromStrError::BalanceHold(error) => { + write!(f, "balance-hold from string error: {}", error) + } FromStrError::UnknownPrefix => write!(f, "unknown prefix for key"), } } @@ -480,18 +494,19 @@ impl Key { Key::Bid(_) => String::from("Key::Bid"), Key::Withdraw(_) => String::from("Key::Unbond"), Key::Dictionary(_) => String::from("Key::Dictionary"), - Key::SystemEntityRegistry => String::from("Key::SystemContractRegistry"), + Key::SystemEntityRegistry => String::from("Key::SystemEntityRegistry"), Key::EraSummary => String::from("Key::EraSummary"), Key::Unbond(_) => String::from("Key::Unbond"), Key::ChainspecRegistry => String::from("Key::ChainspecRegistry"), Key::ChecksumRegistry => String::from("Key::ChecksumRegistry"), Key::BidAddr(_) => String::from("Key::BidAddr"), Key::Package(_) => String::from("Key::Package"), - Key::AddressableEntity(..) => String::from("Key::AddressableEntity"), - Key::ByteCode(..) => String::from("Key::ByteCode"), + Key::AddressableEntity(_) => String::from("Key::AddressableEntity"), + Key::ByteCode(_) => String::from("Key::ByteCode"), Key::Message(_) => String::from("Key::Message"), Key::NamedKey(_) => String::from("Key::NamedKey"), Key::BlockMessageCount => String::from("Key::BlockMessageCount"), + Key::BalanceHold(_) => String::from("Key::BalanceHold"), } } @@ -517,12 +532,18 @@ impl Key { Key::Account(account_hash) => account_hash.to_formatted_string(), Key::Hash(addr) => format!("{}{}", HASH_PREFIX, base16::encode_lower(&addr)), Key::URef(uref) => uref.to_formatted_string(), - Key::Transfer(transfer_addr) => transfer_addr.to_formatted_string(), - Key::DeployInfo(addr) => { + Key::Transfer(transfer_v1_addr) => { + format!( + "{}{}", + TRANSFER_PREFIX, + base16::encode_lower(&transfer_v1_addr.value()) + ) + } + Key::DeployInfo(deploy_hash) => { format!( "{}{}", DEPLOY_INFO_PREFIX, - base16::encode_lower(addr.as_ref()) + base16::encode_lower(deploy_hash.as_ref()) ) } Key::EraInfo(era_id) => { @@ -547,7 +568,7 @@ impl Key { Key::SystemEntityRegistry => { format!( "{}{}", - SYSTEM_CONTRACT_REGISTRY_PREFIX, + SYSTEM_ENTITY_REGISTRY_PREFIX, base16::encode_lower(&PADDING_BYTES) ) } @@ -598,6 +619,10 @@ impl Key { base16::encode_lower(&PADDING_BYTES) ) } + Key::BalanceHold(balance_hold_addr) => { + let tail = BalanceHoldAddr::to_formatted_string(&balance_hold_addr); + format!("{}{}", BALANCE_HOLD_PREFIX, tail) + } } } @@ -625,10 +650,12 @@ impl Key { return Ok(Key::DeployInfo(DeployHash::new(Digest::from(hash_array)))); } - match TransferAddr::from_formatted_str(input) { - Ok(transfer_addr) => return Ok(Key::Transfer(transfer_addr)), - Err(TransferFromStrError::InvalidPrefix) => {} - Err(error) => return Err(error.into()), + if let Some(hex) = input.strip_prefix(TRANSFER_PREFIX) { + let addr = checksummed_hex::decode(hex) + .map_err(|error| FromStrError::Transfer(TransferFromStrError::from(error)))?; + let addr_array = <[u8; TRANSFER_ADDR_LENGTH]>::try_from(addr.as_ref()) + .map_err(|error| FromStrError::Transfer(TransferFromStrError::from(error)))?; + return Ok(Key::Transfer(TransferAddr::new(addr_array))); } match URef::from_formatted_str(input) { @@ -652,6 +679,12 @@ impl Key { return Ok(Key::EraInfo(era_id)); } + // note: BALANCE_HOLD must come before BALANCE due to overlapping head (balance-) + if let Some(hex) = input.strip_prefix(BALANCE_HOLD_PREFIX) { + let balance_hold_addr = BalanceHoldAddr::from_formatted_string(hex)?; + return Ok(Key::BalanceHold(balance_hold_addr)); + } + if let Some(hex) = input.strip_prefix(BALANCE_PREFIX) { let addr = checksummed_hex::decode(hex) .map_err(|error| FromStrError::Balance(error.to_string()))?; @@ -728,11 +761,11 @@ impl Key { return Ok(Key::Dictionary(addr)); } - if let Some(registry_address) = input.strip_prefix(SYSTEM_CONTRACT_REGISTRY_PREFIX) { + if let Some(registry_address) = input.strip_prefix(SYSTEM_ENTITY_REGISTRY_PREFIX) { let padded_bytes = checksummed_hex::decode(registry_address) - .map_err(|error| FromStrError::SystemContractRegistry(error.to_string()))?; + .map_err(|error| FromStrError::SystemEntityRegistry(error.to_string()))?; let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| { - FromStrError::SystemContractRegistry( + FromStrError::SystemEntityRegistry( "Failed to deserialize system registry key".to_string(), ) })?; @@ -772,7 +805,9 @@ impl Key { match EntityAddr::from_formatted_str(input) { Ok(entity_addr) => return Ok(Key::AddressableEntity(entity_addr)), Err(addressable_entity::FromStrError::InvalidPrefix) => {} - Err(error) => return Err(FromStrError::AddressableEntity(error.to_string())), + Err(error) => { + return Err(FromStrError::AddressableEntity(error.to_string())); + } } match ByteCodeAddr::from_formatted_string(input) { @@ -797,7 +832,7 @@ impl Key { let padded_bytes = checksummed_hex::decode(message_count) .map_err(|error| FromStrError::BlockMessageCount(error.to_string()))?; let _padding: [u8; 32] = TryFrom::try_from(padded_bytes.as_ref()).map_err(|_| { - FromStrError::SystemContractRegistry( + FromStrError::SystemEntityRegistry( "Failed to deserialize block message count key".to_string(), ) })?; @@ -903,6 +938,16 @@ impl Key { } } + /// Returns a reference to the inner `BalanceHoldAddr` if `self` is of type + /// [`Key::BalanceHold`], otherwise returns `None`. + pub fn as_balance_hold(&self) -> Option<&BalanceHoldAddr> { + if let Self::BalanceHold(addr) = self { + Some(addr) + } else { + None + } + } + /// Returns the inner [`URef`] if `self` is of type [`Key::URef`], otherwise returns `None`. pub fn into_uref(self) -> Option { match self { @@ -955,11 +1000,9 @@ impl Key { entity_hash: AddressableEntityHash, ) -> Self { let entity_addr = match entity_kind_tag { - EntityKindTag::System => EntityAddr::new_system_entity_addr(entity_hash.value()), - EntityKindTag::Account => EntityAddr::new_account_entity_addr(entity_hash.value()), - EntityKindTag::SmartContract => { - EntityAddr::new_contract_entity_addr(entity_hash.value()) - } + EntityKindTag::System => EntityAddr::new_system(entity_hash.value()), + EntityKindTag::Account => EntityAddr::new_account(entity_hash.value()), + EntityKindTag::SmartContract => EntityAddr::new_smart_contract(entity_hash.value()), }; Key::AddressableEntity(entity_addr) @@ -1034,7 +1077,7 @@ impl Key { } } - /// Returns if they inner Key is for a system contract entity. + /// Returns if the inner address is for a system contract entity. pub fn is_system_key(&self) -> bool { if let Self::AddressableEntity(entity_addr) = self { return match entity_addr.tag() { @@ -1068,6 +1111,104 @@ impl Key { false } } + + /// Is the record under this key readable by the entity corresponding to the imputed address? + pub fn is_readable(&self, entity_addr: &EntityAddr) -> bool { + if entity_addr.is_system() { + // the system can read everything + return true; + } + let ret = match self { + Key::BidAddr(_) => { + // all bids are public information + true + } + Key::URef(uref) => { + // uref's require explicit permissions + uref.is_readable() + } + Key::SystemEntityRegistry | Key::Package(_) => { + // the system entities and all packages are public info + true + } + Key::Unbond(account_hash) => { + // and an account holder can read their own account record + entity_addr.tag() == EntityKindTag::Account + && entity_addr.value() == account_hash.value() + } + Key::NamedKey(named_key_addr) => { + // an entity can read its own named keys + &named_key_addr.entity_addr() == entity_addr + } + Key::ByteCode(_) + | Key::Account(_) + | Key::Hash(_) + | Key::AddressableEntity(_) + | Key::Balance(_) + | Key::BalanceHold(_) + | Key::Dictionary(_) + | Key::Message(_) + | Key::BlockMessageCount => true, + _ => false, + }; + if !ret { + let reading_entity_key = Key::AddressableEntity(*entity_addr); + warn!(?reading_entity_key, attempted_key=?self, "attempt to read without permission") + } + ret + } + + /// Is the record under this key addable by the entity corresponding to the imputed address? + pub fn is_addable(&self, entity_addr: &EntityAddr) -> bool { + // unlike readable / writeable which are universally supported, + // only some data types support commutative add / extension + let ret = match self { + Key::URef(uref) => uref.is_addable(), + Key::AddressableEntity(addr_entity_addr) => { + // an entity can extend itself (only associated keys, currently) + entity_addr == addr_entity_addr + } + Key::NamedKey(named_key_addr) => { + // an entity can extend its own named keys + &named_key_addr.entity_addr() == entity_addr + } + _ => { + // other data types do not support commutative addition / extension + let adding_entity_key = Key::AddressableEntity(*entity_addr); + warn!(?adding_entity_key, attempted_key=?self, "attempt to add on an unsupported data type"); + return false; // we want the above more explicit warn message, not both messages. + } + }; + if !ret { + let adding_entity_key = Key::AddressableEntity(*entity_addr); + warn!(?adding_entity_key, attempted_key=?self, "attempt to add without permission"); + } + ret + } + + /// Is the record under this key writeable by the entity corresponding to the imputed address? + pub fn is_writeable(&self, entity_addr: &EntityAddr) -> bool { + if entity_addr.is_system() { + // the system can write everything + return true; + } + let ret = match self { + Key::URef(uref) => uref.is_writeable(), + Key::NamedKey(named_key_addr) => { + // an entity can write to its own named keys + &named_key_addr.entity_addr() == entity_addr + } + _ => { + // only the system can write other kinds of records + false + } + }; + if !ret { + let writing_entity_key = Key::AddressableEntity(*entity_addr); + warn!(?writing_entity_key, attempted_key=?self, "attempt to write without permission") + } + ret + } } impl Display for Key { @@ -1076,7 +1217,9 @@ impl Display for Key { Key::Account(account_hash) => write!(f, "Key::Account({})", account_hash), Key::Hash(addr) => write!(f, "Key::Hash({})", base16::encode_lower(&addr)), Key::URef(uref) => write!(f, "Key::{}", uref), /* Display impl for URef will append */ - Key::Transfer(transfer_addr) => write!(f, "Key::Transfer({})", transfer_addr), + Key::Transfer(transfer_v1_addr) => { + write!(f, "Key::Transfer({})", transfer_v1_addr) + } Key::DeployInfo(addr) => write!( f, "Key::DeployInfo({})", @@ -1093,7 +1236,7 @@ impl Display for Key { } Key::SystemEntityRegistry => write!( f, - "Key::SystemContractRegistry({})", + "Key::SystemEntityRegistry({})", base16::encode_lower(&PADDING_BYTES) ), Key::EraSummary => write!( @@ -1140,6 +1283,9 @@ impl Display for Key { base16::encode_lower(&PADDING_BYTES) ) } + Key::BalanceHold(balance_hold_addr) => { + write!(f, "Key::BalanceHold({})", balance_hold_addr) + } } } } @@ -1163,7 +1309,7 @@ impl Tagged for Key { Key::Bid(_) => KeyTag::Bid, Key::Withdraw(_) => KeyTag::Withdraw, Key::Dictionary(_) => KeyTag::Dictionary, - Key::SystemEntityRegistry => KeyTag::SystemContractRegistry, + Key::SystemEntityRegistry => KeyTag::SystemEntityRegistry, Key::EraSummary => KeyTag::EraSummary, Key::Unbond(_) => KeyTag::Unbond, Key::ChainspecRegistry => KeyTag::ChainspecRegistry, @@ -1175,6 +1321,7 @@ impl Tagged for Key { Key::Message(_) => KeyTag::Message, Key::NamedKey(_) => KeyTag::NamedKey, Key::BlockMessageCount => KeyTag::BlockMessageCount, + Key::BalanceHold(_) => KeyTag::BalanceHold, } } } @@ -1198,12 +1345,6 @@ impl From for Key { } } -impl From for Key { - fn from(transfer_addr: TransferAddr) -> Key { - Key::Transfer(transfer_addr) - } -} - impl From for Key { fn from(package_hash: PackageHash) -> Key { Key::Package(package_hash.value()) @@ -1267,29 +1408,29 @@ impl ToBytes for Key { Key::Bid(_) => KEY_BID_SERIALIZED_LENGTH, Key::Withdraw(_) => KEY_WITHDRAW_SERIALIZED_LENGTH, Key::Dictionary(_) => KEY_DICTIONARY_SERIALIZED_LENGTH, - Key::SystemEntityRegistry => KEY_SYSTEM_CONTRACT_REGISTRY_SERIALIZED_LENGTH, + Key::SystemEntityRegistry => KEY_SYSTEM_ENTITY_REGISTRY_SERIALIZED_LENGTH, Key::EraSummary => KEY_ERA_SUMMARY_SERIALIZED_LENGTH, Key::Unbond(_) => KEY_UNBOND_SERIALIZED_LENGTH, Key::ChainspecRegistry => KEY_CHAINSPEC_REGISTRY_SERIALIZED_LENGTH, Key::ChecksumRegistry => KEY_CHECKSUM_REGISTRY_SERIALIZED_LENGTH, - Key::BidAddr(bid_addr) => match bid_addr.tag() { - BidAddrTag::Unified => KEY_ID_SERIALIZED_LENGTH + bid_addr.serialized_length() - 1, - BidAddrTag::Validator | BidAddrTag::Delegator => { - KEY_ID_SERIALIZED_LENGTH + bid_addr.serialized_length() - } - }, + Key::BidAddr(bid_addr) => KEY_ID_SERIALIZED_LENGTH + bid_addr.serialized_length(), Key::Package(_) => KEY_PACKAGE_SERIALIZED_LENGTH, - Key::AddressableEntity(..) => { - U8_SERIALIZED_LENGTH + KEY_ID_SERIALIZED_LENGTH + ADDR_LENGTH + Key::AddressableEntity(entity_addr) => { + KEY_ID_SERIALIZED_LENGTH + entity_addr.serialized_length() } Key::ByteCode(byte_code_addr) => { - U8_SERIALIZED_LENGTH + byte_code_addr.serialized_length() + KEY_ID_SERIALIZED_LENGTH + byte_code_addr.serialized_length() } Key::Message(message_addr) => { KEY_ID_SERIALIZED_LENGTH + message_addr.serialized_length() } - Key::NamedKey(named_key) => U8_SERIALIZED_LENGTH + named_key.serialized_length(), + Key::NamedKey(named_key_addr) => { + KEY_ID_SERIALIZED_LENGTH + named_key_addr.serialized_length() + } Key::BlockMessageCount => KEY_BLOCK_MESSAGE_COUNT_SERIALIZED_LENGTH, + Key::BalanceHold(balance_hold_addr) => { + U8_SERIALIZED_LENGTH + balance_hold_addr.serialized_length() + } } } @@ -1312,19 +1453,13 @@ impl ToBytes for Key { | Key::ChainspecRegistry | Key::ChecksumRegistry | Key::BlockMessageCount => PADDING_BYTES.write_bytes(writer), - Key::BidAddr(bid_addr) => match bid_addr.tag() { - BidAddrTag::Unified => { - let bytes = bid_addr.to_bytes()?; - writer.extend(&bytes[1..]); - Ok(()) - } - BidAddrTag::Validator | BidAddrTag::Delegator => bid_addr.write_bytes(writer), - }, + Key::BidAddr(bid_addr) => bid_addr.write_bytes(writer), Key::Package(package_addr) => package_addr.write_bytes(writer), Key::AddressableEntity(entity_addr) => entity_addr.write_bytes(writer), Key::ByteCode(byte_code_addr) => byte_code_addr.write_bytes(writer), Key::Message(message_addr) => message_addr.write_bytes(writer), Key::NamedKey(named_key_addr) => named_key_addr.write_bytes(writer), + Key::BalanceHold(balance_hold_addr) => balance_hold_addr.write_bytes(writer), } } } @@ -1346,8 +1481,8 @@ impl FromBytes for Key { Ok((Key::URef(uref), rem)) } KeyTag::Transfer => { - let (transfer_addr, rem) = TransferAddr::from_bytes(remainder)?; - Ok((Key::Transfer(transfer_addr), rem)) + let (transfer_v1_addr, rem) = TransferAddr::from_bytes(remainder)?; + Ok((Key::Transfer(transfer_v1_addr), rem)) } KeyTag::DeployInfo => { let (deploy_hash, rem) = DeployHash::from_bytes(remainder)?; @@ -1373,7 +1508,7 @@ impl FromBytes for Key { let (addr, rem) = DictionaryAddr::from_bytes(remainder)?; Ok((Key::Dictionary(addr), rem)) } - KeyTag::SystemContractRegistry => { + KeyTag::SystemEntityRegistry => { let (_, rem) = <[u8; 32]>::from_bytes(remainder)?; Ok((Key::SystemEntityRegistry, rem)) } @@ -1421,6 +1556,10 @@ impl FromBytes for Key { let (_, rem) = <[u8; 32]>::from_bytes(remainder)?; Ok((Key::BlockMessageCount, rem)) } + KeyTag::BalanceHold => { + let (balance_hold_addr, rem) = BalanceHoldAddr::from_bytes(remainder)?; + Ok((Key::BalanceHold(balance_hold_addr), rem)) + } } } } @@ -1452,17 +1591,18 @@ fn please_add_to_distribution_impl(key: Key) { Key::Message(_) => unimplemented!(), Key::NamedKey(_) => unimplemented!(), Key::BlockMessageCount => unimplemented!(), + Key::BalanceHold(_) => unimplemented!(), } } #[cfg(any(feature = "testing", test))] impl Distribution for Standard { fn sample(&self, rng: &mut R) -> Key { - match rng.gen_range(0..=21) { + match rng.gen_range(0..=22) { 0 => Key::Account(rng.gen()), 1 => Key::Hash(rng.gen()), 2 => Key::URef(rng.gen()), - 3 => Key::Transfer(rng.gen()), + 3 => Key::Transfer(TransferAddr::new(rng.gen())), 4 => Key::DeployInfo(DeployHash::from_raw(rng.gen())), 5 => Key::EraInfo(EraId::new(rng.gen())), 6 => Key::Balance(rng.gen()), @@ -1479,8 +1619,9 @@ impl Distribution for Standard { 17 => Key::AddressableEntity(rng.gen()), 18 => Key::ByteCode(rng.gen()), 19 => Key::Message(rng.gen()), - 20 => Key::NamedKey(rng.gen()), + 20 => Key::NamedKey(NamedKeyAddr::new_named_key_entry(rng.gen(), rng.gen())), 21 => Key::BlockMessageCount, + 22 => Key::BalanceHold(rng.gen()), _ => unreachable!(), } } @@ -1502,7 +1643,7 @@ mod serde_helpers { Bid(&'a AccountHash), Withdraw(&'a AccountHash), Dictionary(&'a HashAddr), - SystemContractRegistry, + SystemEntityRegistry, EraSummary, Unbond(&'a AccountHash), ChainspecRegistry, @@ -1514,6 +1655,7 @@ mod serde_helpers { Message(&'a MessageAddr), NamedKey(&'a NamedKeyAddr), BlockMessageCount, + BalanceHold(&'a BalanceHoldAddr), } #[derive(Deserialize)] @@ -1529,7 +1671,7 @@ mod serde_helpers { Bid(AccountHash), Withdraw(AccountHash), Dictionary(DictionaryAddr), - SystemContractRegistry, + SystemEntityRegistry, EraSummary, Unbond(AccountHash), ChainspecRegistry, @@ -1541,6 +1683,7 @@ mod serde_helpers { Message(MessageAddr), NamedKey(NamedKeyAddr), BlockMessageCount, + BalanceHold(BalanceHoldAddr), } impl<'a> From<&'a Key> for BinarySerHelper<'a> { @@ -1549,14 +1692,14 @@ mod serde_helpers { Key::Account(account_hash) => BinarySerHelper::Account(account_hash), Key::Hash(hash_addr) => BinarySerHelper::Hash(hash_addr), Key::URef(uref) => BinarySerHelper::URef(uref), - Key::Transfer(transfer_addr) => BinarySerHelper::Transfer(transfer_addr), + Key::Transfer(transfer_v1_addr) => BinarySerHelper::Transfer(transfer_v1_addr), Key::DeployInfo(deploy_hash) => BinarySerHelper::DeployInfo(deploy_hash), Key::EraInfo(era_id) => BinarySerHelper::EraInfo(era_id), Key::Balance(uref_addr) => BinarySerHelper::Balance(uref_addr), Key::Bid(account_hash) => BinarySerHelper::Bid(account_hash), Key::Withdraw(account_hash) => BinarySerHelper::Withdraw(account_hash), Key::Dictionary(addr) => BinarySerHelper::Dictionary(addr), - Key::SystemEntityRegistry => BinarySerHelper::SystemContractRegistry, + Key::SystemEntityRegistry => BinarySerHelper::SystemEntityRegistry, Key::EraSummary => BinarySerHelper::EraSummary, Key::Unbond(account_hash) => BinarySerHelper::Unbond(account_hash), Key::ChainspecRegistry => BinarySerHelper::ChainspecRegistry, @@ -1568,8 +1711,11 @@ mod serde_helpers { BinarySerHelper::AddressableEntity(entity_addr) } Key::ByteCode(byte_code_addr) => BinarySerHelper::ByteCode(byte_code_addr), - Key::NamedKey(named_key) => BinarySerHelper::NamedKey(named_key), + Key::NamedKey(named_key_addr) => BinarySerHelper::NamedKey(named_key_addr), Key::BlockMessageCount => BinarySerHelper::BlockMessageCount, + Key::BalanceHold(balance_hold_addr) => { + BinarySerHelper::BalanceHold(balance_hold_addr) + } } } } @@ -1580,14 +1726,14 @@ mod serde_helpers { BinaryDeserHelper::Account(account_hash) => Key::Account(account_hash), BinaryDeserHelper::Hash(hash_addr) => Key::Hash(hash_addr), BinaryDeserHelper::URef(uref) => Key::URef(uref), - BinaryDeserHelper::Transfer(transfer_addr) => Key::Transfer(transfer_addr), + BinaryDeserHelper::Transfer(transfer_v1_addr) => Key::Transfer(transfer_v1_addr), BinaryDeserHelper::DeployInfo(deploy_hash) => Key::DeployInfo(deploy_hash), BinaryDeserHelper::EraInfo(era_id) => Key::EraInfo(era_id), BinaryDeserHelper::Balance(uref_addr) => Key::Balance(uref_addr), BinaryDeserHelper::Bid(account_hash) => Key::Bid(account_hash), BinaryDeserHelper::Withdraw(account_hash) => Key::Withdraw(account_hash), BinaryDeserHelper::Dictionary(addr) => Key::Dictionary(addr), - BinaryDeserHelper::SystemContractRegistry => Key::SystemEntityRegistry, + BinaryDeserHelper::SystemEntityRegistry => Key::SystemEntityRegistry, BinaryDeserHelper::EraSummary => Key::EraSummary, BinaryDeserHelper::Unbond(account_hash) => Key::Unbond(account_hash), BinaryDeserHelper::ChainspecRegistry => Key::ChainspecRegistry, @@ -1601,6 +1747,9 @@ mod serde_helpers { BinaryDeserHelper::ByteCode(byte_code_addr) => Key::ByteCode(byte_code_addr), BinaryDeserHelper::NamedKey(named_key_addr) => Key::NamedKey(named_key_addr), BinaryDeserHelper::BlockMessageCount => Key::BlockMessageCount, + BinaryDeserHelper::BalanceHold(balance_hold_addr) => { + Key::BalanceHold(balance_hold_addr) + } } } } @@ -1636,12 +1785,12 @@ mod tests { use crate::{ account::ACCOUNT_HASH_FORMATTED_STRING_PREFIX, bytesrepr::{Error, FromBytes}, - transfer::TRANSFER_ADDR_FORMATTED_STRING_PREFIX, uref::UREF_FORMATTED_STRING_PREFIX, - AccessRights, URef, + AccessRights, BlockTime, URef, }; - const ENTITY_PREFIX: &str = "addressable-entity-"; + const TRANSFER_ADDR_FORMATTED_STRING_PREFIX: &str = "transfer-"; + const ENTITY_PREFIX: &str = "entity-"; const ACCOUNT_ENTITY_PREFIX: &str = "account-"; const BYTE_CODE_PREFIX: &str = "byte-code-"; @@ -1660,34 +1809,36 @@ mod tests { const DELEGATOR_BID_KEY: Key = Key::BidAddr(BidAddr::new_delegator_addr(([2; 32], [9; 32]))); const WITHDRAW_KEY: Key = Key::Withdraw(AccountHash::new([42; 32])); const DICTIONARY_KEY: Key = Key::Dictionary([42; 32]); - const SYSTEM_CONTRACT_REGISTRY_KEY: Key = Key::SystemEntityRegistry; + const SYSTEM_ENTITY_REGISTRY_KEY: Key = Key::SystemEntityRegistry; const ERA_SUMMARY_KEY: Key = Key::EraSummary; const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32])); const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry; const CHECKSUM_REGISTRY_KEY: Key = Key::ChecksumRegistry; const PACKAGE_KEY: Key = Key::Package([42; 32]); const ADDRESSABLE_ENTITY_SYSTEM_KEY: Key = - Key::AddressableEntity(EntityAddr::new_system_entity_addr([42; 32])); + Key::AddressableEntity(EntityAddr::new_system([42; 32])); const ADDRESSABLE_ENTITY_ACCOUNT_KEY: Key = - Key::AddressableEntity(EntityAddr::new_account_entity_addr([42; 32])); + Key::AddressableEntity(EntityAddr::new_account([42; 32])); const ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY: Key = - Key::AddressableEntity(EntityAddr::new_contract_entity_addr([42; 32])); + Key::AddressableEntity(EntityAddr::new_smart_contract([42; 32])); const BYTE_CODE_EMPTY_KEY: Key = Key::ByteCode(ByteCodeAddr::Empty); const BYTE_CODE_V1_WASM_KEY: Key = Key::ByteCode(ByteCodeAddr::V1CasperWasm([42; 32])); const MESSAGE_TOPIC_KEY: Key = Key::Message(MessageAddr::new_topic_addr( - EntityAddr::new_contract_entity_addr([42u8; 32]), + EntityAddr::new_smart_contract([42; 32]), TopicNameHash::new([42; 32]), )); const MESSAGE_KEY: Key = Key::Message(MessageAddr::new_message_addr( - EntityAddr::new_contract_entity_addr([42u8; 32]), + EntityAddr::new_smart_contract([42u8; 32]), TopicNameHash::new([2; 32]), 15, )); const NAMED_KEY: Key = Key::NamedKey(NamedKeyAddr::new_named_key_entry( - EntityAddr::new_contract_entity_addr([42; 32]), + EntityAddr::new_smart_contract([42; 32]), [43; 32], )); const BLOCK_MESSAGE_COUNT: Key = Key::BlockMessageCount; + const BALANCE_HOLD: Key = + Key::BalanceHold(BalanceHoldAddr::new_gas([42; 32], BlockTime::new(100))); const KEYS: &[Key] = &[ ACCOUNT_KEY, HASH_KEY, @@ -1699,7 +1850,7 @@ mod tests { BID_KEY, WITHDRAW_KEY, DICTIONARY_KEY, - SYSTEM_CONTRACT_REGISTRY_KEY, + SYSTEM_ENTITY_REGISTRY_KEY, ERA_SUMMARY_KEY, UNBOND_KEY, CHAINSPEC_REGISTRY_KEY, @@ -1717,6 +1868,7 @@ mod tests { MESSAGE_KEY, NAMED_KEY, BLOCK_MESSAGE_COUNT, + BALANCE_HOLD, ]; const HEX_STRING: &str = "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"; const TOPIC_NAME_HEX_STRING: &str = @@ -1826,9 +1978,9 @@ mod tests { format!("Key::Dictionary({})", HEX_STRING) ); assert_eq!( - format!("{}", SYSTEM_CONTRACT_REGISTRY_KEY), + format!("{}", SYSTEM_ENTITY_REGISTRY_KEY), format!( - "Key::SystemContractRegistry({})", + "Key::SystemEntityRegistry({})", base16::encode_lower(&PADDING_BYTES) ) ); @@ -1884,26 +2036,24 @@ mod tests { assert_eq!( format!("{}", MESSAGE_TOPIC_KEY), format!( - "Key::Message(addressable-entity-contract-{}-{})", + "Key::Message(entity-contract-{}-{})", HEX_STRING, HEX_STRING ) ); - assert_eq!( format!("{}", MESSAGE_KEY), format!( - "Key::Message(addressable-entity-contract-{}-{}-{})", + "Key::Message(entity-contract-{}-{}-{})", HEX_STRING, TOPIC_NAME_HEX_STRING, MESSAGE_INDEX_HEX_STRING ) ); - assert_eq!( format!("{}", BLOCK_MESSAGE_COUNT), format!( "Key::BlockMessageCount({})", base16::encode_lower(&PADDING_BYTES) ) - ) + ); } #[test] @@ -2093,7 +2243,7 @@ mod tests { Key::from_formatted_str(TRANSFER_ADDR_FORMATTED_STRING_PREFIX) .unwrap_err() .to_string() - .starts_with("transfer-key from string error: ") + .starts_with("legacy-transfer-key from string error: ") ); assert!(Key::from_formatted_str(DEPLOY_INFO_PREFIX) .unwrap_err() @@ -2119,7 +2269,7 @@ mod tests { .unwrap_err() .to_string() .starts_with("dictionary-key from string error: ")); - assert!(Key::from_formatted_str(SYSTEM_CONTRACT_REGISTRY_PREFIX) + assert!(Key::from_formatted_str(SYSTEM_ENTITY_REGISTRY_PREFIX) .unwrap_err() .to_string() .starts_with("system-contract-registry-key from string error: ")); @@ -2185,6 +2335,15 @@ mod tests { Key::from_formatted_str(no_prefix).unwrap_err().to_string(), "unknown prefix for key" ); + + let balance_hold_err = Key::from_formatted_str(BALANCE_HOLD_PREFIX) + .unwrap_err() + .to_string(); + assert!( + balance_hold_err.starts_with("balance-hold from string error: "), + "{}", + bid_addr_err + ); } #[test] @@ -2245,26 +2404,55 @@ mod tests { round_trip(&Key::Dictionary(zeros)); round_trip(&Key::Unbond(AccountHash::new(zeros))); round_trip(&Key::Package(zeros)); - round_trip(&Key::AddressableEntity(EntityAddr::new_system_entity_addr( + round_trip(&Key::AddressableEntity(EntityAddr::new_system(zeros))); + round_trip(&Key::AddressableEntity(EntityAddr::new_account(zeros))); + round_trip(&Key::AddressableEntity(EntityAddr::new_smart_contract( zeros, ))); - round_trip(&Key::AddressableEntity( - EntityAddr::new_account_entity_addr(zeros), - )); - round_trip(&Key::AddressableEntity( - EntityAddr::new_contract_entity_addr(zeros), - )); round_trip(&Key::ByteCode(ByteCodeAddr::Empty)); round_trip(&Key::ByteCode(ByteCodeAddr::V1CasperWasm(zeros))); round_trip(&Key::Message(MessageAddr::new_topic_addr( - EntityAddr::new_contract_entity_addr(zeros), + EntityAddr::new_smart_contract(zeros), nines.into(), ))); round_trip(&Key::Message(MessageAddr::new_message_addr( - EntityAddr::new_contract_entity_addr(zeros), + EntityAddr::new_smart_contract(zeros), nines.into(), 1, ))); + round_trip(&Key::NamedKey(NamedKeyAddr::default())); round_trip(&Key::BlockMessageCount); + round_trip(&Key::BalanceHold(BalanceHoldAddr::default())); + } + + #[test] + fn bytesrepr_serialization_roundtrip() { + bytesrepr::test_serialization_roundtrip(&ACCOUNT_KEY); + bytesrepr::test_serialization_roundtrip(&HASH_KEY); + bytesrepr::test_serialization_roundtrip(&UREF_KEY); + bytesrepr::test_serialization_roundtrip(&TRANSFER_KEY); + bytesrepr::test_serialization_roundtrip(&DEPLOY_INFO_KEY); + bytesrepr::test_serialization_roundtrip(&ERA_INFO_KEY); + bytesrepr::test_serialization_roundtrip(&BALANCE_KEY); + bytesrepr::test_serialization_roundtrip(&BID_KEY); + bytesrepr::test_serialization_roundtrip(&WITHDRAW_KEY); + bytesrepr::test_serialization_roundtrip(&DICTIONARY_KEY); + bytesrepr::test_serialization_roundtrip(&SYSTEM_ENTITY_REGISTRY_KEY); + bytesrepr::test_serialization_roundtrip(&ERA_SUMMARY_KEY); + bytesrepr::test_serialization_roundtrip(&UNBOND_KEY); + bytesrepr::test_serialization_roundtrip(&CHAINSPEC_REGISTRY_KEY); + bytesrepr::test_serialization_roundtrip(&CHECKSUM_REGISTRY_KEY); + bytesrepr::test_serialization_roundtrip(&UNIFIED_BID_KEY); + bytesrepr::test_serialization_roundtrip(&VALIDATOR_BID_KEY); + bytesrepr::test_serialization_roundtrip(&DELEGATOR_BID_KEY); + bytesrepr::test_serialization_roundtrip(&PACKAGE_KEY); + bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SYSTEM_KEY); + bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_ACCOUNT_KEY); + bytesrepr::test_serialization_roundtrip(&ADDRESSABLE_ENTITY_SMART_CONTRACT_KEY); + bytesrepr::test_serialization_roundtrip(&BYTE_CODE_EMPTY_KEY); + bytesrepr::test_serialization_roundtrip(&BYTE_CODE_V1_WASM_KEY); + bytesrepr::test_serialization_roundtrip(&MESSAGE_TOPIC_KEY); + bytesrepr::test_serialization_roundtrip(&MESSAGE_KEY); + bytesrepr::test_serialization_roundtrip(&NAMED_KEY); } } diff --git a/types/src/lib.rs b/types/src/lib.rs index e274b12fe4..424445ca62 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -20,14 +20,13 @@ #[cfg_attr(not(test), macro_use)] extern crate alloc; -extern crate core; +extern crate core; mod access_rights; pub mod account; pub mod addressable_entity; pub mod api_error; mod auction_state; -pub mod binary_port; mod block; mod block_time; mod byte_code; @@ -55,7 +54,7 @@ pub mod global_state; mod json_pretty_printer; mod key; mod motes; -pub mod package; +mod package; mod peers_map; mod phase; mod protocol_version; @@ -106,7 +105,7 @@ pub use block::{ }; #[cfg(any(all(feature = "std", feature = "testing"), test))] pub use block::{TestBlockBuilder, TestBlockV1Builder}; -pub use block_time::{BlockTime, BLOCKTIME_SERIALIZED_LENGTH}; +pub use block_time::{BlockTime, HoldsEpoch, BLOCKTIME_SERIALIZED_LENGTH}; pub use byte_code::{ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind}; #[cfg(any(feature = "std", test))] @@ -117,10 +116,10 @@ pub use chainspec::{ GenesisConfig, GenesisConfigBuilder, GenesisValidator, GlobalStateUpdate, GlobalStateUpdateConfig, GlobalStateUpdateError, HandlePaymentCosts, HighwayConfig, HostFunction, HostFunctionCost, HostFunctionCosts, LegacyRequiredFinality, MessageLimits, - MintCosts, NetworkConfig, NextUpgrade, OpcodeCosts, ProtocolConfig, ProtocolUpgradeConfig, - RefundHandling, StandardPaymentCosts, StorageCosts, SystemConfig, TransactionConfig, - TransactionV1Config, VacancyConfig, ValidatorConfig, WasmConfig, - DEFAULT_HOST_FUNCTION_NEW_DICTIONARY, + MintCosts, NetworkConfig, NextUpgrade, OpcodeCosts, PricingHandling, ProtocolConfig, + ProtocolUpgradeConfig, RefundHandling, StandardPaymentCosts, StorageCosts, SystemConfig, + TransactionConfig, TransactionV1Config, VacancyConfig, ValidatorConfig, WasmConfig, + DEFAULT_BALANCE_HOLD_INTERVAL, DEFAULT_HOST_FUNCTION_NEW_DICTIONARY, DEFAULT_REFUND_HANDLING, }; #[cfg(any(all(feature = "std", feature = "testing"), test))] pub use chainspec::{ @@ -137,11 +136,10 @@ pub use chainspec::{ DEFAULT_INSTALL_UPGRADE_GAS_LIMIT, DEFAULT_INTEGER_COMPARISON_COST, DEFAULT_LOAD_COST, DEFAULT_LOCAL_COST, DEFAULT_MAX_PAYMENT_MOTES, DEFAULT_MAX_STACK_HEIGHT, DEFAULT_MIN_TRANSFER_MOTES, DEFAULT_MUL_COST, DEFAULT_NEW_DICTIONARY_COST, DEFAULT_NOP_COST, - DEFAULT_REFUND_HANDLING, DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT, DEFAULT_STORE_COST, - DEFAULT_TRANSFER_COST, DEFAULT_UNREACHABLE_COST, DEFAULT_WASM_MAX_MEMORY, + DEFAULT_STANDARD_TRANSACTION_GAS_LIMIT, DEFAULT_STORE_COST, DEFAULT_TRANSFER_COST, + DEFAULT_UNREACHABLE_COST, DEFAULT_WASM_MAX_MEMORY, }; pub use cl_type::{named_key_type, CLType, CLTyped}; - pub use cl_value::{ handle_stored_dictionary_value, CLTypeMismatch, CLValue, CLValueError, ChecksumRegistry, DictionaryValue as CLValueDictionary, SystemEntityRegistry, @@ -168,6 +166,7 @@ pub use motes::Motes; #[doc(inline)] pub use package::{ EntityVersion, EntityVersionKey, EntityVersions, Group, Groups, Package, PackageHash, + PackageStatus, ENTITY_INITIAL_VERSION, }; pub use peers_map::{PeerEntry, Peers}; pub use phase::{Phase, PHASE_SERIALIZED_LENGTH}; @@ -180,23 +179,26 @@ pub use tagged::Tagged; #[cfg(any(feature = "std", test))] pub use timestamp::serde_option_time_diff; pub use timestamp::{TimeDiff, Timestamp}; +#[cfg(any(feature = "std", test))] +pub use transaction::GasLimited; pub use transaction::{ - AddressableEntityIdentifier, Approval, ApprovalsHash, Deploy, DeployConfigFailure, - DeployDecodeFromJsonError, DeployError, DeployExcessiveSizeError, DeployHash, DeployHeader, - DeployId, ExecutableDeployItem, ExecutableDeployItemIdentifier, ExecutionInfo, InitiatorAddr, - NamedArg, PackageIdentifier, PricingMode, RuntimeArgs, Transaction, TransactionCategory, - TransactionConfigFailure, TransactionEntryPoint, TransactionHash, TransactionHeader, - TransactionId, TransactionInvocationTarget, TransactionRuntime, TransactionScheduling, - TransactionSessionKind, TransactionTarget, TransactionV1, TransactionV1Body, - TransactionV1ConfigFailure, TransactionV1DecodeFromJsonError, TransactionV1Error, - TransactionV1ExcessiveSizeError, TransactionV1Hash, TransactionV1Header, TransferTarget, + AddressableEntityIdentifier, Approval, ApprovalsHash, Categorized as CategorizedTransaction, + Deploy, DeployDecodeFromJsonError, DeployError, DeployExcessiveSizeError, DeployHash, + DeployHeader, DeployId, ExecutableDeployItem, ExecutableDeployItemIdentifier, ExecutionInfo, + InitiatorAddr, InvalidDeploy, InvalidTransaction, InvalidTransactionV1, NamedArg, + PackageIdentifier, PricingMode, RuntimeArgs, Transaction, TransactionCategory, + TransactionEntryPoint, TransactionHash, TransactionHeader, TransactionId, + TransactionInvocationTarget, TransactionRuntime, TransactionScheduling, TransactionSessionKind, + TransactionTarget, TransactionV1, TransactionV1Body, TransactionV1DecodeFromJsonError, + TransactionV1Error, TransactionV1ExcessiveSizeError, TransactionV1Hash, TransactionV1Header, + TransferTarget, }; #[cfg(any(feature = "std", test))] pub use transaction::{ DeployBuilder, DeployBuilderError, TransactionV1Builder, TransactionV1BuilderError, }; pub use transfer::{ - FromStrError as TransferFromStrError, Transfer, TransferAddr, TRANSFER_ADDR_LENGTH, + Transfer, TransferAddr, TransferFromStrError, TransferV1, TransferV2, TRANSFER_ADDR_LENGTH, }; pub use transfer_result::{TransferResult, TransferredTo}; pub use uref::{ diff --git a/types/src/motes.rs b/types/src/motes.rs index 8008a81c61..2361f9b867 100644 --- a/types/src/motes.rs +++ b/types/src/motes.rs @@ -24,8 +24,13 @@ pub struct Motes(U512); impl Motes { /// Constructs a new `Motes`. - pub fn new(value: U512) -> Motes { - Motes(value) + pub fn new>(value: T) -> Self { + Motes(value.into()) + } + + /// Constructs a new `Motes` with value `0`. + pub const fn zero() -> Self { + Motes(U512::zero()) } /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred. @@ -46,7 +51,7 @@ impl Motes { /// Converts the given `gas` to `Motes` by multiplying them by `conv_rate`. /// /// Returns `None` if an arithmetic overflow occurred. - pub fn from_gas(gas: Gas, conv_rate: u64) -> Option { + pub fn from_gas(gas: Gas, conv_rate: u8) -> Option { gas.value() .checked_mul(U512::from(conv_rate)) .map(Self::new) @@ -97,7 +102,7 @@ impl Mul for Motes { impl Zero for Motes { fn zero() -> Self { - Motes::new(U512::zero()) + Motes::zero() } fn is_zero(&self) -> bool { @@ -124,7 +129,7 @@ impl ToBytes for Motes { impl FromBytes for Motes { fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { let (value, remainder) = FromBytes::from_bytes(bytes)?; - Ok((Motes::new(value), remainder)) + Ok((Motes(value), remainder)) } } @@ -137,7 +142,7 @@ mod tests { #[test] fn should_be_able_to_get_instance_of_motes() { let initial_value = 1; - let motes = Motes::new(U512::from(initial_value)); + let motes = Motes::new(initial_value); assert_eq!( initial_value, motes.value().as_u64(), @@ -147,18 +152,18 @@ mod tests { #[test] fn should_be_able_to_compare_two_instances_of_motes() { - let left_motes = Motes::new(U512::from(1)); - let right_motes = Motes::new(U512::from(1)); + let left_motes = Motes::new(1); + let right_motes = Motes::new(1); assert_eq!(left_motes, right_motes, "should be equal"); - let right_motes = Motes::new(U512::from(2)); + let right_motes = Motes::new(2); assert_ne!(left_motes, right_motes, "should not be equal") } #[test] fn should_be_able_to_add_two_instances_of_motes() { - let left_motes = Motes::new(U512::from(1)); - let right_motes = Motes::new(U512::from(1)); - let expected_motes = Motes::new(U512::from(2)); + let left_motes = Motes::new(1); + let right_motes = Motes::new(1); + let expected_motes = Motes::new(2); assert_eq!( (left_motes + right_motes), expected_motes, @@ -168,9 +173,9 @@ mod tests { #[test] fn should_be_able_to_subtract_two_instances_of_motes() { - let left_motes = Motes::new(U512::from(1)); - let right_motes = Motes::new(U512::from(1)); - let expected_motes = Motes::new(U512::from(0)); + let left_motes = Motes::new(1); + let right_motes = Motes::new(1); + let expected_motes = Motes::new(0); assert_eq!( (left_motes - right_motes), expected_motes, @@ -180,9 +185,9 @@ mod tests { #[test] fn should_be_able_to_multiply_two_instances_of_motes() { - let left_motes = Motes::new(U512::from(100)); - let right_motes = Motes::new(U512::from(10)); - let expected_motes = Motes::new(U512::from(1000)); + let left_motes = Motes::new(100); + let right_motes = Motes::new(10); + let expected_motes = Motes::new(1000); assert_eq!( (left_motes * right_motes), expected_motes, @@ -192,9 +197,9 @@ mod tests { #[test] fn should_be_able_to_divide_two_instances_of_motes() { - let left_motes = Motes::new(U512::from(1000)); - let right_motes = Motes::new(U512::from(100)); - let expected_motes = Motes::new(U512::from(10)); + let left_motes = Motes::new(1000); + let right_motes = Motes::new(100); + let expected_motes = Motes::new(10); assert_eq!( (left_motes / right_motes), expected_motes, @@ -204,34 +209,34 @@ mod tests { #[test] fn should_be_able_to_convert_from_motes() { - let gas = Gas::new(U512::from(100)); + let gas = Gas::new(100); let motes = Motes::from_gas(gas, 10).expect("should have value"); - let expected_motes = Motes::new(U512::from(1000)); + let expected_motes = Motes::new(1000); assert_eq!(motes, expected_motes, "should be equal") } #[test] fn should_be_able_to_default() { let motes = Motes::default(); - let expected_motes = Motes::new(U512::from(0)); + let expected_motes = Motes::new(0); assert_eq!(motes, expected_motes, "should be equal") } #[test] fn should_be_able_to_compare_relative_value() { - let left_motes = Motes::new(U512::from(100)); - let right_motes = Motes::new(U512::from(10)); + let left_motes = Motes::new(100); + let right_motes = Motes::new(10); assert!(left_motes > right_motes, "should be gt"); - let right_motes = Motes::new(U512::from(100)); + let right_motes = Motes::new(100); assert!(left_motes >= right_motes, "should be gte"); assert!(left_motes <= right_motes, "should be lte"); - let left_motes = Motes::new(U512::from(10)); + let left_motes = Motes::new(10); assert!(left_motes < right_motes, "should be lt"); } #[test] fn should_default() { - let left_motes = Motes::new(U512::from(0)); + let left_motes = Motes::new(0); let right_motes = Motes::default(); assert_eq!(left_motes, right_motes, "should be equal"); let u512 = U512::zero(); diff --git a/types/src/package.rs b/types/src/package.rs index 9da3492e9b..d3c84a4b5a 100644 --- a/types/src/package.rs +++ b/types/src/package.rs @@ -29,20 +29,6 @@ use crate::{ AddressableEntityHash, CLType, CLTyped, HashAddr, BLAKE2B_DIGEST_LENGTH, KEY_HASH_LENGTH, }; -/// Maximum number of distinct user groups. -pub const MAX_GROUPS: u8 = 10; -/// Maximum number of URefs which can be assigned across all user groups. -pub const MAX_TOTAL_UREFS: usize = 100; - -/// The tag for Contract Packages associated with Wasm stored on chain. -pub const PACKAGE_KIND_WASM_TAG: u8 = 0; -/// The tag for Contract Package associated with a native contract implementation. -pub const PACKAGE_KIND_SYSTEM_CONTRACT_TAG: u8 = 1; -/// The tag for Contract Package associated with an Account hash. -pub const PACKAGE_KIND_ACCOUNT_TAG: u8 = 2; -/// The tag for Contract Packages associated with legacy packages. -pub const PACKAGE_KIND_LEGACY_TAG: u8 = 3; - const PACKAGE_STRING_PREFIX: &str = "contract-package-"; // We need to support the legacy prefix of "contract-package-wasm". const PACKAGE_STRING_LEGACY_EXTRA_PREFIX: &str = "wasm"; @@ -947,7 +933,7 @@ mod tests { vec![], CLType::U32, EntryPointAccess::groups(&["Group 2"]), - EntryPointType::Session, + EntryPointType::Caller, ); ret.insert(entrypoint.name().to_owned(), entrypoint); let entrypoint = EntryPoint::new( @@ -955,7 +941,7 @@ mod tests { vec![Parameter::new("Foo", CLType::U32)], CLType::U32, EntryPointAccess::groups(&["Group 1"]), - EntryPointType::Session, + EntryPointType::Caller, ); ret.insert(entrypoint.name().to_owned(), entrypoint); ret diff --git a/types/src/peers_map.rs b/types/src/peers_map.rs index c7a2833463..1ac5da20a1 100644 --- a/types/src/peers_map.rs +++ b/types/src/peers_map.rs @@ -9,15 +9,13 @@ use alloc::{ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; +#[cfg(any(feature = "testing", test))] use core::iter; - -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use rand::Rng; -#[cfg(test)] -use crate::testing::TestRng; - /// Node peer entry. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] @@ -30,7 +28,7 @@ pub struct PeerEntry { } impl PeerEntry { - #[cfg(test)] + #[cfg(any(feature = "testing", test))] pub(crate) fn random(rng: &mut TestRng) -> Self { Self { node_id: rng.random_string(10..20), @@ -76,8 +74,9 @@ impl Peers { self.0 } - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { let count = rng.gen_range(0..10); let peers = iter::repeat(()) .map(|_| PeerEntry::random(rng)) diff --git a/types/src/protocol_version.rs b/types/src/protocol_version.rs index 2651772fa4..7be95caae0 100644 --- a/types/src/protocol_version.rs +++ b/types/src/protocol_version.rs @@ -73,7 +73,7 @@ impl ProtocolVersion { } /// Returns the inner [`SemVer`]. - pub fn value(&self) -> SemVer { + pub const fn value(&self) -> SemVer { self.0 } diff --git a/types/src/stored_value.rs b/types/src/stored_value.rs index 9a3b146f59..a9af67b6d6 100644 --- a/types/src/stored_value.rs +++ b/types/src/stored_value.rs @@ -24,7 +24,7 @@ use crate::{ contracts::{Contract, ContractPackage}, package::Package, system::auction::{Bid, BidKind, EraInfo, UnbondingPurse, WithdrawPurse}, - AddressableEntity, ByteCode, CLValue, DeployInfo, Transfer, + AddressableEntity, ByteCode, CLValue, DeployInfo, TransferV1, }; pub use global_state_identifier::GlobalStateIdentifier; pub use type_mismatch::TypeMismatch; @@ -37,7 +37,7 @@ enum Tag { ContractWasm = 2, Contract = 3, ContractPackage = 4, - Transfer = 5, + LegacyTransfer = 5, DeployInfo = 6, EraInfo = 7, Bid = 8, @@ -49,7 +49,7 @@ enum Tag { ByteCode = 14, MessageTopic = 15, Message = 16, - NamedKeyValue = 17, + NamedKey = 17, } /// A value stored in Global State. @@ -72,8 +72,8 @@ pub enum StoredValue { Contract(Contract), /// A contract package. ContractPackage(ContractPackage), - /// A `Transfer`. - Transfer(Transfer), + /// A version 1 (legacy) transfer. + LegacyTransfer(TransferV1), /// Info about a deploy. DeployInfo(DeployInfo), /// Info about an era. @@ -141,10 +141,10 @@ impl StoredValue { } } - /// Returns a reference to the wrapped `Transfer` if this is a `Transfer` variant. - pub fn as_transfer(&self) -> Option<&Transfer> { + /// Returns a reference to the wrapped `TransferV1` if this is a `LegacyTransfer` variant. + pub fn as_legacy_transfer(&self) -> Option<&TransferV1> { match self { - StoredValue::Transfer(transfer) => Some(transfer), + StoredValue::LegacyTransfer(transfer_v1) => Some(transfer_v1), _ => None, } } @@ -273,10 +273,10 @@ impl StoredValue { } } - /// Returns the `Transfer` if this is a `Transfer` variant. - pub fn into_transfer(self) -> Option { + /// Returns the `TransferV1` if this is a `LegacyTransfer` variant. + pub fn into_legacy_transfer(self) -> Option { match self { - StoredValue::Transfer(transfer) => Some(transfer), + StoredValue::LegacyTransfer(transfer_v1) => Some(transfer_v1), _ => None, } } @@ -347,7 +347,7 @@ impl StoredValue { StoredValue::ContractWasm(_) => "ContractWasm".to_string(), StoredValue::Contract(_) => "Contract".to_string(), StoredValue::ContractPackage(_) => "ContractPackage".to_string(), - StoredValue::Transfer(_) => "Transfer".to_string(), + StoredValue::LegacyTransfer(_) => "LegacyTransfer".to_string(), StoredValue::DeployInfo(_) => "DeployInfo".to_string(), StoredValue::EraInfo(_) => "EraInfo".to_string(), StoredValue::Bid(_) => "Bid".to_string(), @@ -359,7 +359,7 @@ impl StoredValue { StoredValue::Package(_) => "Package".to_string(), StoredValue::MessageTopic(_) => "MessageTopic".to_string(), StoredValue::Message(_) => "Message".to_string(), - StoredValue::NamedKey(_) => "NamedKeyValue".to_string(), + StoredValue::NamedKey(_) => "NamedKey".to_string(), } } @@ -370,7 +370,7 @@ impl StoredValue { StoredValue::ContractWasm(_) => Tag::ContractWasm, StoredValue::ContractPackage(_) => Tag::ContractPackage, StoredValue::Contract(_) => Tag::Contract, - StoredValue::Transfer(_) => Tag::Transfer, + StoredValue::LegacyTransfer(_) => Tag::LegacyTransfer, StoredValue::DeployInfo(_) => Tag::DeployInfo, StoredValue::EraInfo(_) => Tag::EraInfo, StoredValue::Bid(_) => Tag::Bid, @@ -382,7 +382,7 @@ impl StoredValue { StoredValue::ByteCode(_) => Tag::ByteCode, StoredValue::MessageTopic(_) => Tag::MessageTopic, StoredValue::Message(_) => Tag::Message, - StoredValue::NamedKey(_) => Tag::NamedKeyValue, + StoredValue::NamedKey(_) => Tag::NamedKey, } } } @@ -557,13 +557,16 @@ impl TryFrom for AddressableEntity { } } -impl TryFrom for Transfer { +impl TryFrom for TransferV1 { type Error = TypeMismatch; fn try_from(value: StoredValue) -> Result { match value { - StoredValue::Transfer(transfer) => Ok(transfer), - _ => Err(TypeMismatch::new("Transfer".to_string(), value.type_name())), + StoredValue::LegacyTransfer(transfer_v1) => Ok(transfer_v1), + _ => Err(TypeMismatch::new( + "LegacyTransfer".to_string(), + value.type_name(), + )), } } } @@ -630,7 +633,7 @@ impl TryFrom for NamedKeyValue { } impl ToBytes for StoredValue { - fn to_bytes(&self) -> Result, bytesrepr::Error> { + fn to_bytes(&self) -> Result, Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; Ok(buffer) @@ -646,7 +649,7 @@ impl ToBytes for StoredValue { StoredValue::ContractPackage(contract_package) => { contract_package.serialized_length() } - StoredValue::Transfer(transfer) => transfer.serialized_length(), + StoredValue::LegacyTransfer(transfer_v1) => transfer_v1.serialized_length(), StoredValue::DeployInfo(deploy_info) => deploy_info.serialized_length(), StoredValue::EraInfo(era_info) => era_info.serialized_length(), StoredValue::Bid(bid) => bid.serialized_length(), @@ -664,33 +667,30 @@ impl ToBytes for StoredValue { } } - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + fn write_bytes(&self, writer: &mut Vec) -> Result<(), Error> { writer.push(self.tag() as u8); match self { - StoredValue::CLValue(cl_value) => cl_value.write_bytes(writer)?, - StoredValue::Account(account) => account.write_bytes(writer)?, - StoredValue::ContractWasm(contract_wasm) => contract_wasm.write_bytes(writer)?, - StoredValue::Contract(contract_header) => contract_header.write_bytes(writer)?, - StoredValue::ContractPackage(contract_package) => { - contract_package.write_bytes(writer)? - } - StoredValue::Transfer(transfer) => transfer.write_bytes(writer)?, - StoredValue::DeployInfo(deploy_info) => deploy_info.write_bytes(writer)?, - StoredValue::EraInfo(era_info) => era_info.write_bytes(writer)?, - StoredValue::Bid(bid) => bid.write_bytes(writer)?, - StoredValue::Withdraw(unbonding_purses) => unbonding_purses.write_bytes(writer)?, - StoredValue::Unbonding(unbonding_purses) => unbonding_purses.write_bytes(writer)?, - StoredValue::AddressableEntity(entity) => entity.write_bytes(writer)?, - StoredValue::BidKind(bid_kind) => bid_kind.write_bytes(writer)?, - StoredValue::Package(package) => package.write_bytes(writer)?, - StoredValue::ByteCode(byte_code) => byte_code.write_bytes(writer)?, + StoredValue::CLValue(cl_value) => cl_value.write_bytes(writer), + StoredValue::Account(account) => account.write_bytes(writer), + StoredValue::ContractWasm(contract_wasm) => contract_wasm.write_bytes(writer), + StoredValue::Contract(contract_header) => contract_header.write_bytes(writer), + StoredValue::ContractPackage(contract_package) => contract_package.write_bytes(writer), + StoredValue::LegacyTransfer(transfer_v1) => transfer_v1.write_bytes(writer), + StoredValue::DeployInfo(deploy_info) => deploy_info.write_bytes(writer), + StoredValue::EraInfo(era_info) => era_info.write_bytes(writer), + StoredValue::Bid(bid) => bid.write_bytes(writer), + StoredValue::Withdraw(unbonding_purses) => unbonding_purses.write_bytes(writer), + StoredValue::Unbonding(unbonding_purses) => unbonding_purses.write_bytes(writer), + StoredValue::AddressableEntity(entity) => entity.write_bytes(writer), + StoredValue::BidKind(bid_kind) => bid_kind.write_bytes(writer), + StoredValue::Package(package) => package.write_bytes(writer), + StoredValue::ByteCode(byte_code) => byte_code.write_bytes(writer), StoredValue::MessageTopic(message_topic_summary) => { - message_topic_summary.write_bytes(writer)? + message_topic_summary.write_bytes(writer) } - StoredValue::Message(message_digest) => message_digest.write_bytes(writer)?, - StoredValue::NamedKey(named_key_value) => named_key_value.write_bytes(writer)?, - }; - Ok(()) + StoredValue::Message(message_digest) => message_digest.write_bytes(writer), + StoredValue::NamedKey(named_key_value) => named_key_value.write_bytes(writer), + } } } @@ -714,8 +714,11 @@ impl FromBytes for StoredValue { } tag if tag == Tag::Contract as u8 => Contract::from_bytes(remainder) .map(|(contract, remainder)| (StoredValue::Contract(contract), remainder)), - tag if tag == Tag::Transfer as u8 => Transfer::from_bytes(remainder) - .map(|(transfer, remainder)| (StoredValue::Transfer(transfer), remainder)), + tag if tag == Tag::LegacyTransfer as u8 => { + TransferV1::from_bytes(remainder).map(|(transfer_v1, remainder)| { + (StoredValue::LegacyTransfer(transfer_v1), remainder) + }) + } tag if tag == Tag::DeployInfo as u8 => DeployInfo::from_bytes(remainder) .map(|(deploy_info, remainder)| (StoredValue::DeployInfo(deploy_info), remainder)), tag if tag == Tag::EraInfo as u8 => EraInfo::from_bytes(remainder) @@ -746,7 +749,7 @@ impl FromBytes for StoredValue { }), tag if tag == Tag::Message as u8 => MessageChecksum::from_bytes(remainder) .map(|(checksum, remainder)| (StoredValue::Message(checksum), remainder)), - tag if tag == Tag::NamedKeyValue as u8 => { + tag if tag == Tag::NamedKey as u8 => { NamedKeyValue::from_bytes(remainder).map(|(named_key_value, remainder)| { (StoredValue::NamedKey(named_key_value), remainder) }) @@ -761,80 +764,45 @@ mod serde_helpers { #[derive(Serialize)] pub(super) enum BinarySerHelper<'a> { - /// A CLValue. CLValue(&'a CLValue), - /// An account. Account(&'a Account), ContractWasm(&'a ContractWasm), - /// A contract. Contract(&'a Contract), - /// A `Package`. ContractPackage(&'a ContractPackage), - /// A `Transfer`. - Transfer(&'a Transfer), - /// Info about a deploy. + LegacyTransfer(&'a TransferV1), DeployInfo(&'a DeployInfo), - /// Info about an era. EraInfo(&'a EraInfo), - /// Variant that stores [`Bid`]. Bid(&'a Bid), - /// Variant that stores withdraw information. Withdraw(&'a Vec), - /// Unbonding information. Unbonding(&'a Vec), - /// An `AddressableEntity`. AddressableEntity(&'a AddressableEntity), - /// Variant that stores [`BidKind`]. BidKind(&'a BidKind), - /// Package. Package(&'a Package), - /// A record of byte code. ByteCode(&'a ByteCode), - /// Variant that stores [`MessageTopicSummary`]. MessageTopic(&'a MessageTopicSummary), - /// Variant that stores a [`MessageChecksum`]. Message(&'a MessageChecksum), - /// A record for NamedKey. NamedKey(&'a NamedKeyValue), } #[derive(Deserialize)] pub(super) enum BinaryDeserHelper { - /// A CLValue. CLValue(CLValue), - /// An account. Account(Account), - /// A contract wasm. ContractWasm(ContractWasm), - /// A contract. Contract(Contract), - /// A `Package`. ContractPackage(ContractPackage), - /// A `Transfer`. - Transfer(Transfer), - /// Info about a deploy. + LegacyTransfer(TransferV1), DeployInfo(DeployInfo), - /// Info about an era. EraInfo(EraInfo), - /// Variant that stores [`Bid`]. Bid(Box), - /// Variant that stores withdraw information. Withdraw(Vec), - /// Unbonding information. Unbonding(Vec), - /// An `AddressableEntity`. AddressableEntity(AddressableEntity), - /// Variant that stores [`BidKind`]. BidKind(BidKind), - /// A record of a Package. Package(Package), - /// A record of byte code. ByteCode(ByteCode), - /// Variant that stores [`MessageTopicSummary`]. MessageTopic(MessageTopicSummary), - /// Variant that stores [`MessageChecksum`]. Message(MessageChecksum), - /// A record for NamedKey. NamedKey(NamedKeyValue), } @@ -846,7 +814,7 @@ mod serde_helpers { StoredValue::ContractWasm(payload) => BinarySerHelper::ContractWasm(payload), StoredValue::Contract(payload) => BinarySerHelper::Contract(payload), StoredValue::ContractPackage(payload) => BinarySerHelper::ContractPackage(payload), - StoredValue::Transfer(payload) => BinarySerHelper::Transfer(payload), + StoredValue::LegacyTransfer(payload) => BinarySerHelper::LegacyTransfer(payload), StoredValue::DeployInfo(payload) => BinarySerHelper::DeployInfo(payload), StoredValue::EraInfo(payload) => BinarySerHelper::EraInfo(payload), StoredValue::Bid(payload) => BinarySerHelper::Bid(payload), @@ -877,7 +845,7 @@ mod serde_helpers { BinaryDeserHelper::ContractPackage(payload) => { StoredValue::ContractPackage(payload) } - BinaryDeserHelper::Transfer(payload) => StoredValue::Transfer(payload), + BinaryDeserHelper::LegacyTransfer(payload) => StoredValue::LegacyTransfer(payload), BinaryDeserHelper::DeployInfo(payload) => StoredValue::DeployInfo(payload), BinaryDeserHelper::EraInfo(payload) => StoredValue::EraInfo(payload), BinaryDeserHelper::Bid(bid) => StoredValue::Bid(bid), diff --git a/types/src/stored_value/global_state_identifier.rs b/types/src/stored_value/global_state_identifier.rs index e99cf27a25..a909f05f52 100644 --- a/types/src/stored_value/global_state_identifier.rs +++ b/types/src/stored_value/global_state_identifier.rs @@ -1,17 +1,17 @@ use alloc::vec::Vec; -#[cfg(test)] -use rand::Rng; #[cfg(feature = "json-schema")] use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, BlockHash, BlockIdentifier, Digest, }; +#[cfg(any(feature = "testing", test))] +use rand::Rng; const BLOCK_HASH_TAG: u8 = 0; const BLOCK_HEIGHT_TAG: u8 = 1; @@ -31,8 +31,9 @@ pub enum GlobalStateIdentifier { } impl GlobalStateIdentifier { - #[cfg(test)] - pub(crate) fn random(rng: &mut TestRng) -> Self { + /// Random. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { match rng.gen_range(0..3) { 0 => Self::BlockHash(BlockHash::random(rng)), 1 => Self::BlockHeight(rng.gen()), diff --git a/types/src/system/auction/constants.rs b/types/src/system/auction/constants.rs index f3038f8e90..63b414bfab 100644 --- a/types/src/system/auction/constants.rs +++ b/types/src/system/auction/constants.rs @@ -36,10 +36,6 @@ pub const ARG_VALIDATOR_PUBLIC_KEYS: &str = "validator_public_keys"; pub const ARG_NEW_VALIDATOR: &str = "new_validator"; /// Named constant for `era_id`. pub const ARG_ERA_ID: &str = "era_id"; -/// Named constant for `validator_public_key`. -pub const ARG_VALIDATOR_PUBLIC_KEY: &str = "validator_public_key"; -/// Named constant for `delegator_public_key`. -pub const ARG_DELEGATOR_PUBLIC_KEY: &str = "delegator_public_key"; /// Named constant for `validator_slots` argument. pub const ARG_VALIDATOR_SLOTS: &str = VALIDATOR_SLOTS_KEY; /// Named constant for `mint_contract_package_hash` diff --git a/types/src/system/auction/entry_points.rs b/types/src/system/auction/entry_points.rs index 252550e548..6a1974b303 100644 --- a/types/src/system/auction/entry_points.rs +++ b/types/src/system/auction/entry_points.rs @@ -2,9 +2,9 @@ use crate::{ system::auction::{ DelegationRate, ValidatorWeights, ARG_AMOUNT, ARG_DELEGATION_RATE, ARG_DELEGATOR, ARG_ERA_END_TIMESTAMP_MILLIS, ARG_NEW_VALIDATOR, ARG_PUBLIC_KEY, ARG_VALIDATOR, - ARG_VALIDATOR_PUBLIC_KEY, METHOD_ACTIVATE_BID, METHOD_ADD_BID, METHOD_DELEGATE, - METHOD_DISTRIBUTE, METHOD_GET_ERA_VALIDATORS, METHOD_READ_ERA_ID, METHOD_REDELEGATE, - METHOD_RUN_AUCTION, METHOD_SLASH, METHOD_UNDELEGATE, METHOD_WITHDRAW_BID, + METHOD_ACTIVATE_BID, METHOD_ADD_BID, METHOD_DELEGATE, METHOD_DISTRIBUTE, + METHOD_GET_ERA_VALIDATORS, METHOD_READ_ERA_ID, METHOD_REDELEGATE, METHOD_RUN_AUCTION, + METHOD_SLASH, METHOD_UNDELEGATE, METHOD_WITHDRAW_BID, }, CLType, CLTyped, EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, Parameter, PublicKey, U512, @@ -21,7 +21,7 @@ pub fn auction_entry_points() -> EntryPoints { vec![], Option::::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -34,7 +34,7 @@ pub fn auction_entry_points() -> EntryPoints { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -46,7 +46,7 @@ pub fn auction_entry_points() -> EntryPoints { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -59,7 +59,7 @@ pub fn auction_entry_points() -> EntryPoints { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -72,7 +72,7 @@ pub fn auction_entry_points() -> EntryPoints { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -86,7 +86,7 @@ pub fn auction_entry_points() -> EntryPoints { ], U512::cl_type(), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -95,7 +95,7 @@ pub fn auction_entry_points() -> EntryPoints { vec![Parameter::new(ARG_ERA_END_TIMESTAMP_MILLIS, u64::cl_type())], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -104,7 +104,7 @@ pub fn auction_entry_points() -> EntryPoints { vec![], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -116,7 +116,7 @@ pub fn auction_entry_points() -> EntryPoints { )], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -125,16 +125,16 @@ pub fn auction_entry_points() -> EntryPoints { vec![], CLType::U64, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); let entry_point = EntryPoint::new( METHOD_ACTIVATE_BID, - vec![Parameter::new(ARG_VALIDATOR_PUBLIC_KEY, CLType::PublicKey)], + vec![Parameter::new(ARG_VALIDATOR, CLType::PublicKey)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/types/src/system/auction/error.rs b/types/src/system/auction/error.rs index dc3f3d88fa..1fb8bff3e0 100644 --- a/types/src/system/auction/error.rs +++ b/types/src/system/auction/error.rs @@ -333,6 +333,12 @@ pub enum Error { /// assert_eq!(50, Error::ForgedReference as u8); /// ``` ForgedReference = 50, + /// Unable to find purse. + /// ``` + /// # use casper_types::system::auction::Error; + /// assert_eq!(51, Error::MissingPurse as u8); + /// ``` + MissingPurse = 51, } impl Display for Error { @@ -389,6 +395,7 @@ impl Display for Error { Error::GetAccumulationPurse => formatter.write_str("Get accumulation purse error"), Error::TransferToAdministrator => formatter.write_str("Transfer to administrator error"), Error::ForgedReference => formatter.write_str("Forged reference"), + Error::MissingPurse => formatter.write_str("Missing purse"), } } } @@ -471,6 +478,7 @@ impl TryFrom for Error { d if d == Error::GetAccumulationPurse as u8 => Ok(Error::GetAccumulationPurse), d if d == Error::TransferToAdministrator as u8 => Ok(Error::TransferToAdministrator), d if d == Error::ForgedReference as u8 => Ok(Error::ForgedReference), + d if d == Error::MissingPurse as u8 => Ok(Error::MissingPurse), _ => Err(TryFromU8ForError(())), } } @@ -515,7 +523,7 @@ pub enum PurseLookupError { impl From for Error { fn from(error: PurseLookupError) -> Self { match error { - PurseLookupError::KeyNotFound => Error::MissingKey, + PurseLookupError::KeyNotFound => Error::MissingPurse, PurseLookupError::KeyUnexpectedType => Error::InvalidKeyVariant, } } diff --git a/types/src/system/caller.rs b/types/src/system/caller.rs index b668af2aae..a5e9baf302 100644 --- a/types/src/system/caller.rs +++ b/types/src/system/caller.rs @@ -14,22 +14,22 @@ use crate::{ #[derive(FromPrimitive, ToPrimitive)] #[repr(u8)] pub enum CallerTag { - /// Session tag. - Session = 0, - /// StoredContract tag. - StoredContract, + /// Initiator tag. + Initiator = 0, + /// Entity tag. + Entity, } /// Identity of a calling entity. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Caller { - /// Session - Session { + /// Initiator (calling account) + Initiator { /// The account hash of the caller account_hash: AccountHash, }, - /// AddressableEntity - AddressableEntity { + /// Entity (smart contract / system contract) + Entity { /// The package hash package_hash: PackageHash, /// The entity hash @@ -38,19 +38,16 @@ pub enum Caller { } impl Caller { - /// Creates a [`Caller::Session`]. This represents a call into session code, and + /// Creates a [`Caller::Initiator`]. This represents a call into session code, and /// should only ever happen once in a call stack. - pub fn session(account_hash: AccountHash) -> Self { - Caller::Session { account_hash } + pub fn initiator(account_hash: AccountHash) -> Self { + Caller::Initiator { account_hash } } - /// Creates a [`'Caller::StoredContract`]. This represents a call into a contract with - /// `EntryPointType::Contract`. - pub fn stored_contract( - package_hash: PackageHash, - contract_hash: AddressableEntityHash, - ) -> Self { - Caller::AddressableEntity { + /// Creates a [`'Caller::Entity`]. This represents a call into a contract with + /// `EntryPointType::Called`. + pub fn entity(package_hash: PackageHash, contract_hash: AddressableEntityHash) -> Self { + Caller::Entity { package_hash, entity_hash: contract_hash, } @@ -59,18 +56,18 @@ impl Caller { /// Gets the tag from self. pub fn tag(&self) -> CallerTag { match self { - Caller::Session { .. } => CallerTag::Session, + Caller::Initiator { .. } => CallerTag::Initiator, - Caller::AddressableEntity { .. } => CallerTag::StoredContract, + Caller::Entity { .. } => CallerTag::Entity, } } /// Gets the [`AddressableEntityHash`] for both stored session and stored contract variants. pub fn contract_hash(&self) -> Option<&AddressableEntityHash> { match self { - Caller::Session { .. } => None, + Caller::Initiator { .. } => None, - Caller::AddressableEntity { + Caller::Entity { entity_hash: contract_hash, .. } => Some(contract_hash), @@ -83,9 +80,9 @@ impl ToBytes for Caller { let mut result = bytesrepr::allocate_buffer(self)?; result.push(self.tag() as u8); match self { - Caller::Session { account_hash } => result.append(&mut account_hash.to_bytes()?), + Caller::Initiator { account_hash } => result.append(&mut account_hash.to_bytes()?), - Caller::AddressableEntity { + Caller::Entity { package_hash, entity_hash: contract_hash, } => { @@ -99,8 +96,8 @@ impl ToBytes for Caller { fn serialized_length(&self) -> usize { U8_SERIALIZED_LENGTH + match self { - Caller::Session { account_hash } => account_hash.serialized_length(), - Caller::AddressableEntity { + Caller::Initiator { account_hash } => account_hash.serialized_length(), + Caller::Entity { package_hash, entity_hash: contract_hash, } => package_hash.serialized_length() + contract_hash.serialized_length(), @@ -113,15 +110,15 @@ impl FromBytes for Caller { let (tag, remainder): (u8, &[u8]) = FromBytes::from_bytes(bytes)?; let tag = CallerTag::from_u8(tag).ok_or(bytesrepr::Error::Formatting)?; match tag { - CallerTag::Session => { + CallerTag::Initiator => { let (account_hash, remainder) = AccountHash::from_bytes(remainder)?; - Ok((Caller::Session { account_hash }, remainder)) + Ok((Caller::Initiator { account_hash }, remainder)) } - CallerTag::StoredContract => { + CallerTag::Entity => { let (package_hash, remainder) = PackageHash::from_bytes(remainder)?; let (contract_hash, remainder) = AddressableEntityHash::from_bytes(remainder)?; Ok(( - Caller::AddressableEntity { + Caller::Entity { package_hash, entity_hash: contract_hash, }, diff --git a/types/src/system/handle_payment/constants.rs b/types/src/system/handle_payment/constants.rs index ef0feedd54..24fd10bada 100644 --- a/types/src/system/handle_payment/constants.rs +++ b/types/src/system/handle_payment/constants.rs @@ -13,10 +13,6 @@ pub const METHOD_GET_PAYMENT_PURSE: &str = "get_payment_purse"; pub const METHOD_SET_REFUND_PURSE: &str = "set_refund_purse"; /// Named constant for method `get_refund_purse`. pub const METHOD_GET_REFUND_PURSE: &str = "get_refund_purse"; -/// Named constant for method `finalize_payment`. -pub const METHOD_FINALIZE_PAYMENT: &str = "finalize_payment"; -/// Named constant for method `distribute_accumulated_fees`. -pub const METHOD_DISTRIBUTE_ACCUMULATED_FEES: &str = "distribute_accumulated_fees"; /// Storage for handle payment contract hash. pub const CONTRACT_HASH_KEY: &str = "contract_hash"; diff --git a/types/src/system/handle_payment/entry_points.rs b/types/src/system/handle_payment/entry_points.rs index f07b09f58d..3c7d77e4f1 100644 --- a/types/src/system/handle_payment/entry_points.rs +++ b/types/src/system/handle_payment/entry_points.rs @@ -2,14 +2,11 @@ use alloc::boxed::Box; use crate::{ system::handle_payment::{ - ARG_ACCOUNT, ARG_AMOUNT, ARG_PURSE, METHOD_FINALIZE_PAYMENT, METHOD_GET_PAYMENT_PURSE, - METHOD_GET_REFUND_PURSE, METHOD_SET_REFUND_PURSE, + ARG_PURSE, METHOD_GET_PAYMENT_PURSE, METHOD_GET_REFUND_PURSE, METHOD_SET_REFUND_PURSE, }, CLType, EntryPoint, EntryPointAccess, EntryPointType, EntryPoints, Parameter, }; -use super::METHOD_DISTRIBUTE_ACCUMULATED_FEES; - /// Creates handle payment contract entry points. pub fn handle_payment_entry_points() -> EntryPoints { let mut entry_points = EntryPoints::new(); @@ -19,7 +16,7 @@ pub fn handle_payment_entry_points() -> EntryPoints { vec![], CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(get_payment_purse); @@ -28,7 +25,7 @@ pub fn handle_payment_entry_points() -> EntryPoints { vec![Parameter::new(ARG_PURSE, CLType::URef)], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(set_refund_purse); @@ -37,30 +34,9 @@ pub fn handle_payment_entry_points() -> EntryPoints { vec![], CLType::Option(Box::new(CLType::URef)), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(get_refund_purse); - let finalize_payment = EntryPoint::new( - METHOD_FINALIZE_PAYMENT, - vec![ - Parameter::new(ARG_AMOUNT, CLType::U512), - Parameter::new(ARG_ACCOUNT, CLType::ByteArray(32)), - ], - CLType::Unit, - EntryPointAccess::Public, - EntryPointType::AddressableEntity, - ); - entry_points.add_entry_point(finalize_payment); - - let distribute_accumulated_fees = EntryPoint::new( - METHOD_DISTRIBUTE_ACCUMULATED_FEES, - vec![], - CLType::Unit, - EntryPointAccess::Public, - EntryPointType::AddressableEntity, - ); - entry_points.add_entry_point(distribute_accumulated_fees); - entry_points } diff --git a/types/src/system/handle_payment/error.rs b/types/src/system/handle_payment/error.rs index 77867a360d..449d5694a7 100644 --- a/types/src/system/handle_payment/error.rs +++ b/types/src/system/handle_payment/error.rs @@ -255,6 +255,12 @@ pub enum Error { /// assert_eq!(37, Error::AccumulationPurseKeyUnexpectedType as u8); /// ``` AccumulationPurseKeyUnexpectedType = 37, + /// Internal error: invalid fee and / or refund settings encountered during payment processing. + /// ``` + /// # use casper_types::system::handle_payment::Error; + /// assert_eq!(38, Error::IncompatiblePaymentSettings as u8); + /// ``` + IncompatiblePaymentSettings = 38, } impl Display for Error { @@ -326,6 +332,9 @@ impl Display for Error { Error::AccumulationPurseKeyUnexpectedType => { formatter.write_str("Accumulation purse has unexpected type") } + Error::IncompatiblePaymentSettings => { + formatter.write_str("Incompatible payment settings") + } } } } @@ -400,6 +409,9 @@ impl TryFrom for Error { v if v == Error::AccumulationPurseKeyUnexpectedType as u8 => { Error::AccumulationPurseKeyUnexpectedType } + v if v == Error::IncompatiblePaymentSettings as u8 => { + Error::IncompatiblePaymentSettings + } _ => return Err(()), }; Ok(error) diff --git a/types/src/system/mint.rs b/types/src/system/mint.rs index 4a7e58a170..3b37be8957 100644 --- a/types/src/system/mint.rs +++ b/types/src/system/mint.rs @@ -1,8 +1,10 @@ //! Contains implementation of a Mint contract functionality. +mod balance_hold; mod constants; mod entry_points; mod error; +pub use balance_hold::{BalanceHoldAddr, BalanceHoldAddrTag}; pub use constants::*; pub use entry_points::mint_entry_points; pub use error::Error; diff --git a/types/src/system/mint/balance_hold.rs b/types/src/system/mint/balance_hold.rs new file mode 100644 index 0000000000..4902867e5b --- /dev/null +++ b/types/src/system/mint/balance_hold.rs @@ -0,0 +1,350 @@ +use alloc::{ + format, + string::{String, ToString}, + vec::Vec, +}; + +use core::{ + convert::TryFrom, + fmt::{Debug, Display, Formatter}, +}; + +#[cfg(feature = "datasize")] +use datasize::DataSize; +#[cfg(any(feature = "testing", test))] +use rand::distributions::{Distribution, Standard}; +#[cfg(any(feature = "testing", test))] +use rand::Rng; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + bytesrepr, + bytesrepr::{FromBytes, ToBytes}, + checksummed_hex, + key::FromStrError, + system::auction::Error, + BlockTime, Key, KeyTag, Timestamp, URefAddr, BLOCKTIME_SERIALIZED_LENGTH, UREF_ADDR_LENGTH, +}; + +const GAS_TAG: u8 = 0; + +/// Serialization tag for BalanceHold variants. +#[derive( + Debug, Default, PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize, +)] +#[repr(u8)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] +pub enum BalanceHoldAddrTag { + #[default] + /// Tag for gas variant. + Gas = GAS_TAG, +} + +impl BalanceHoldAddrTag { + /// The length in bytes of a [`BalanceHoldAddrTag`]. + pub const BALANCE_HOLD_ADDR_TAG_LENGTH: usize = 1; + + /// Attempts to map `BalanceHoldAddrTag` from a u8. + pub fn try_from_u8(value: u8) -> Option { + // TryFrom requires std, so doing this instead. + if value == GAS_TAG { + return Some(BalanceHoldAddrTag::Gas); + } + None + } + + /// Returns key prefix for a purse by balance hold addr tag. + pub fn purse_prefix_by_tag(&self, purse_addr: URefAddr) -> Result, bytesrepr::Error> { + let mut ret = Vec::with_capacity(purse_addr.serialized_length() + 2); + ret.push(KeyTag::BalanceHold as u8); + ret.push(*self as u8); + purse_addr.write_bytes(&mut ret)?; + Ok(ret) + } +} + +impl Display for BalanceHoldAddrTag { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + let tag = match self { + BalanceHoldAddrTag::Gas => GAS_TAG, + }; + write!(f, "{}", base16::encode_lower(&[tag])) + } +} + +/// Balance hold address. +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] +pub enum BalanceHoldAddr { + /// Gas hold variant. + Gas { + /// The address of the purse this hold is on. + purse_addr: URefAddr, + /// The block time this hold was placed. + block_time: BlockTime, + }, + // future balance hold variants might allow punitive lockup or settlement periods, etc +} + +impl BalanceHoldAddr { + /// The length in bytes of a [`BalanceHoldAddr`] for a gas hold address. + pub const GAS_HOLD_ADDR_LENGTH: usize = UREF_ADDR_LENGTH + + BalanceHoldAddrTag::BALANCE_HOLD_ADDR_TAG_LENGTH + + BLOCKTIME_SERIALIZED_LENGTH; + + /// Creates a Gas variant instance of [`BalanceHoldAddr`]. + pub(crate) const fn new_gas(purse_addr: URefAddr, block_time: BlockTime) -> BalanceHoldAddr { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } + } + + /// How long is be the serialized value for this instance. + pub fn serialized_length(&self) -> usize { + match self { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } => { + BalanceHoldAddrTag::BALANCE_HOLD_ADDR_TAG_LENGTH + + ToBytes::serialized_length(purse_addr) + + ToBytes::serialized_length(block_time) + } + } + } + + /// Returns the tag of this instance. + pub fn tag(&self) -> BalanceHoldAddrTag { + match self { + BalanceHoldAddr::Gas { .. } => BalanceHoldAddrTag::Gas, + } + } + + /// Returns the `[URefAddr]` for the purse associated with this hold. + pub fn purse_addr(&self) -> URefAddr { + match self { + BalanceHoldAddr::Gas { purse_addr, .. } => *purse_addr, + } + } + + /// Returns the `[BlockTime]` when this hold was written. + pub fn block_time(&self) -> BlockTime { + match self { + BalanceHoldAddr::Gas { block_time, .. } => *block_time, + } + } + + /// Returns the common prefix of all holds on the cited purse. + pub fn balance_hold_prefix(&self) -> Result, Error> { + let purse_addr_bytes = self.purse_addr().to_bytes()?; + let size = 1 + purse_addr_bytes.len(); + let mut ret = Vec::with_capacity(size); + ret.push(KeyTag::BalanceHold as u8); + ret.extend(purse_addr_bytes); + Ok(ret) + } + + /// To formatted string. + pub fn to_formatted_string(&self) -> String { + match self { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } => { + format!( + "{}{}{}", + // also, put the tag in readable form + base16::encode_lower(&GAS_TAG.to_le_bytes()), + base16::encode_lower(purse_addr), + // TODO: we could conceivably stringify the u64 millis instead of bytes-ing + // which would allow visual / human determination of the timestamp + // but on the other hand, how many humans casually do from UNIX EPOCH + // time calculation with their eyeballs? Something to discuss prior to + // shipping. + // BlockTime.value as string instead + base16::encode_lower(&block_time.value().to_le_bytes()) + ) + } + } + } + + /// From formatted string. + pub fn from_formatted_string(hex: &str) -> Result { + let bytes = checksummed_hex::decode(hex) + .map_err(|error| FromStrError::BalanceHold(error.to_string()))?; + if bytes.is_empty() { + return Err(FromStrError::BalanceHold( + "bytes should not be 0 len".to_string(), + )); + } + let tag_bytes = <[u8; BalanceHoldAddrTag::BALANCE_HOLD_ADDR_TAG_LENGTH]>::try_from( + bytes[0..BalanceHoldAddrTag::BALANCE_HOLD_ADDR_TAG_LENGTH].as_ref(), + ) + .map_err(|err| FromStrError::BalanceHold(err.to_string()))?; + let tag = ::from_le_bytes(tag_bytes); + let tag = BalanceHoldAddrTag::try_from_u8(tag).ok_or_else(|| { + FromStrError::BalanceHold("failed to parse balance hold addr tag".to_string()) + })?; + + let uref_addr = URefAddr::try_from(bytes[1..=UREF_ADDR_LENGTH].as_ref()) + .map_err(|err| FromStrError::BalanceHold(err.to_string()))?; + + // if more tags are added, extend the below logic to handle every case. + // it is possible that it will turn out that all further tags include blocktime + // in which case it can be pulled up out of the tag guard condition. + // however, im erring on the side of future tolerance and guarding it for now. + if tag == BalanceHoldAddrTag::Gas { + let block_time_bytes = + <[u8; BLOCKTIME_SERIALIZED_LENGTH]>::try_from(bytes[33..].as_ref()) + .map_err(|err| FromStrError::BalanceHold(err.to_string()))?; + + let block_time_millis = ::from_le_bytes(block_time_bytes); + let block_time = BlockTime::new(block_time_millis); + Ok(BalanceHoldAddr::new_gas(uref_addr, block_time)) + } else { + Err(FromStrError::BalanceHold("invalid tag".to_string())) + } + } +} + +impl ToBytes for BalanceHoldAddr { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buffer = bytesrepr::allocate_buffer(self)?; + buffer.push(self.tag() as u8); + match self { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } => { + buffer.append(&mut purse_addr.to_bytes()?); + buffer.append(&mut block_time.to_bytes()?) + } + } + Ok(buffer) + } + + fn serialized_length(&self) -> usize { + self.serialized_length() + } +} + +impl FromBytes for BalanceHoldAddr { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (tag, remainder): (u8, &[u8]) = FromBytes::from_bytes(bytes)?; + match tag { + tag if tag == BalanceHoldAddrTag::Gas as u8 => { + let (purse_addr, rem) = URefAddr::from_bytes(remainder)?; + let (block_time, rem) = BlockTime::from_bytes(rem)?; + Ok(( + BalanceHoldAddr::Gas { + purse_addr, + block_time, + }, + rem, + )) + } + _ => Err(bytesrepr::Error::Formatting), + } + } +} + +impl Default for BalanceHoldAddr { + fn default() -> Self { + BalanceHoldAddr::Gas { + purse_addr: URefAddr::default(), + block_time: BlockTime::default(), + } + } +} + +impl From for Key { + fn from(balance_hold_addr: BalanceHoldAddr) -> Self { + Key::BalanceHold(balance_hold_addr) + } +} + +#[cfg(any(feature = "std", test))] +impl TryFrom for BalanceHoldAddr { + type Error = (); + + fn try_from(value: Key) -> Result { + if let Key::BalanceHold(balance_hold_addr) = value { + Ok(balance_hold_addr) + } else { + Err(()) + } + } +} + +impl Display for BalanceHoldAddr { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + let tag = self.tag(); + match self { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } => { + write!( + f, + "{}-{}-{}", + tag, + base16::encode_lower(&purse_addr), + Timestamp::from(block_time.value()) + ) + } + } + } +} + +impl Debug for BalanceHoldAddr { + fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { + match self { + BalanceHoldAddr::Gas { + purse_addr, + block_time, + } => write!( + f, + "BidAddr::Gas({}, {})", + base16::encode_lower(&purse_addr), + Timestamp::from(block_time.value()) + ), + } + } +} + +#[cfg(any(feature = "testing", test))] +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> BalanceHoldAddr { + BalanceHoldAddr::new_gas(rng.gen(), BlockTime::new(rng.gen())) + } +} + +#[cfg(test)] +mod tests { + use crate::{bytesrepr, system::mint::BalanceHoldAddr, BlockTime, Timestamp}; + + #[test] + fn serialization_roundtrip() { + let addr = BalanceHoldAddr::new_gas([1; 32], BlockTime::new(Timestamp::now().millis())); + bytesrepr::test_serialization_roundtrip(&addr); + } +} + +#[cfg(test)] +mod prop_test_gas { + use proptest::prelude::*; + + use crate::{bytesrepr, gens}; + + proptest! { + #[test] + fn test_variant_gas(addr in gens::balance_hold_addr_arb()) { + bytesrepr::test_serialization_roundtrip(&addr); + } + } +} diff --git a/types/src/system/mint/entry_points.rs b/types/src/system/mint/entry_points.rs index 6002b3383b..bc22fcec78 100644 --- a/types/src/system/mint/entry_points.rs +++ b/types/src/system/mint/entry_points.rs @@ -22,7 +22,7 @@ pub fn mint_entry_points() -> EntryPoints { err: Box::new(CLType::U8), }, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -34,7 +34,7 @@ pub fn mint_entry_points() -> EntryPoints { err: Box::new(CLType::U8), }, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -43,7 +43,7 @@ pub fn mint_entry_points() -> EntryPoints { Parameters::new(), CLType::URef, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -52,7 +52,7 @@ pub fn mint_entry_points() -> EntryPoints { vec![Parameter::new(ARG_PURSE, CLType::URef)], CLType::Option(Box::new(CLType::U512)), EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -70,7 +70,7 @@ pub fn mint_entry_points() -> EntryPoints { err: Box::new(CLType::U8), }, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -79,7 +79,7 @@ pub fn mint_entry_points() -> EntryPoints { Parameters::new(), CLType::U512, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); @@ -94,7 +94,7 @@ pub fn mint_entry_points() -> EntryPoints { err: Box::new(CLType::U8), }, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(entry_point); diff --git a/types/src/system/standard_payment/entry_points.rs b/types/src/system/standard_payment/entry_points.rs index 3eeaed52d6..fee12664a7 100644 --- a/types/src/system/standard_payment/entry_points.rs +++ b/types/src/system/standard_payment/entry_points.rs @@ -17,7 +17,7 @@ pub fn standard_payment_entry_points() -> EntryPoints { err: Box::new(CLType::U32), }, EntryPointAccess::Public, - EntryPointType::Session, + EntryPointType::Caller, ); entry_points.add_entry_point(entry_point); diff --git a/types/src/timestamp.rs b/types/src/timestamp.rs index 524d0b1412..76b401d2e8 100644 --- a/types/src/timestamp.rs +++ b/types/src/timestamp.rs @@ -266,7 +266,7 @@ impl FromStr for TimeDiff { impl TimeDiff { /// Returns the time difference as the number of milliseconds since the Unix epoch - pub fn millis(&self) -> u64 { + pub const fn millis(&self) -> u64 { self.0 } diff --git a/types/src/transaction.rs b/types/src/transaction.rs index 4dbbf3b2dc..00b0aa0eb6 100644 --- a/types/src/transaction.rs +++ b/types/src/transaction.rs @@ -2,6 +2,7 @@ mod addressable_entity_identifier; mod approval; mod approvals_hash; mod deploy; +mod error; mod execution_info; mod initiator_addr; #[cfg(any(feature = "std", test))] @@ -20,11 +21,12 @@ mod transaction_scheduling; mod transaction_session_kind; mod transaction_target; mod transaction_v1; +mod transfer_target; use alloc::{collections::BTreeSet, vec::Vec}; use core::fmt::{self, Debug, Display, Formatter}; -#[cfg(feature = "std")] -use std::error::Error as StdError; +#[cfg(any(feature = "std", test))] +use std::hash::Hash; #[cfg(feature = "datasize")] use datasize::DataSize; @@ -40,23 +42,25 @@ use tracing::error; #[cfg(any(all(feature = "std", feature = "testing"), test))] use crate::testing::TestRng; +#[cfg(feature = "json-schema")] +use crate::URef; use crate::{ account::AccountHash, bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, - Digest, SecretKey, Timestamp, + Digest, Phase, SecretKey, TimeDiff, Timestamp, }; -#[cfg(feature = "json-schema")] -use crate::{account::ACCOUNT_HASH_LENGTH, TimeDiff, URef}; +#[cfg(any(feature = "std", test))] +use crate::{Chainspec, Gas, Motes}; pub use addressable_entity_identifier::AddressableEntityIdentifier; pub use approval::Approval; pub use approvals_hash::ApprovalsHash; pub use deploy::{ - Deploy, DeployConfigFailure, DeployDecodeFromJsonError, DeployError, DeployExcessiveSizeError, - DeployHash, DeployHeader, DeployId, ExecutableDeployItem, ExecutableDeployItemIdentifier, - TransferTarget, + Deploy, DeployDecodeFromJsonError, DeployError, DeployExcessiveSizeError, DeployHash, + DeployHeader, DeployId, ExecutableDeployItem, ExecutableDeployItemIdentifier, InvalidDeploy, }; #[cfg(any(feature = "std", test))] pub use deploy::{DeployBuilder, DeployBuilderError}; +pub use error::InvalidTransaction; pub use execution_info::ExecutionInfo; pub use initiator_addr::InitiatorAddr; #[cfg(any(feature = "std", test))] @@ -74,12 +78,13 @@ pub use transaction_scheduling::TransactionScheduling; pub use transaction_session_kind::TransactionSessionKind; pub use transaction_target::TransactionTarget; pub use transaction_v1::{ - TransactionCategory, TransactionV1, TransactionV1Body, TransactionV1ConfigFailure, + InvalidTransactionV1, TransactionCategory, TransactionV1, TransactionV1Body, TransactionV1DecodeFromJsonError, TransactionV1Error, TransactionV1ExcessiveSizeError, TransactionV1Hash, TransactionV1Header, }; #[cfg(any(feature = "std", test))] pub use transaction_v1::{TransactionV1Builder, TransactionV1BuilderError}; +pub use transfer_target::TransferTarget; const DEPLOY_TAG: u8 = 0; const V1_TAG: u8 = 1; @@ -95,10 +100,9 @@ pub(super) static TRANSACTION: Lazy = Lazy::new(|| { "uref-1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b-000", ) .unwrap(); - let to = Some(AccountHash::new([40; ACCOUNT_HASH_LENGTH])); let id = Some(999); - let v1_txn = TransactionV1Builder::new_transfer(source, target, 30_000_000_000_u64, to, id) + let v1_txn = TransactionV1Builder::new_transfer(30_000_000_000_u64, Some(source), target, id) .unwrap() .with_chain_name("casper-example") .with_timestamp(*Timestamp::example()) @@ -109,46 +113,6 @@ pub(super) static TRANSACTION: Lazy = Lazy::new(|| { Transaction::V1(v1_txn) }); -/// A representation of the way in which a transaction failed validation checks. -#[derive(Debug)] -pub enum TransactionConfigFailure { - /// Error details for the Deploy variant. - Deploy(DeployConfigFailure), - /// Error details for the TransactionV1 variant. - V1(TransactionV1ConfigFailure), -} - -impl From for TransactionConfigFailure { - fn from(value: DeployConfigFailure) -> Self { - Self::Deploy(value) - } -} - -impl From for TransactionConfigFailure { - fn from(value: TransactionV1ConfigFailure) -> Self { - Self::V1(value) - } -} - -#[cfg(feature = "std")] -impl StdError for TransactionConfigFailure { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - TransactionConfigFailure::Deploy(deploy) => deploy.source(), - TransactionConfigFailure::V1(v1) => v1.source(), - } - } -} - -impl Display for TransactionConfigFailure { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - TransactionConfigFailure::Deploy(deploy) => write!(f, "{}", deploy), - TransactionConfigFailure::V1(v1) => write!(f, "{}", v1), - } - } -} - /// A versioned wrapper for a transaction or deploy. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr( @@ -175,9 +139,41 @@ impl Transaction { } } + /// Body hash. + pub fn body_hash(&self) -> Digest { + match self { + Transaction::Deploy(deploy) => *deploy.header().body_hash(), + Transaction::V1(v1) => *v1.header().body_hash(), + } + } + + /// Size estimate. + pub fn size_estimate(&self) -> usize { + match self { + Transaction::Deploy(deploy) => deploy.serialized_length(), + Transaction::V1(v1) => v1.serialized_length(), + } + } + + /// Timestamp. + pub fn timestamp(&self) -> Timestamp { + match self { + Transaction::Deploy(deploy) => deploy.header().timestamp(), + Transaction::V1(v1) => v1.header().timestamp(), + } + } + + /// Time to live. + pub fn ttl(&self) -> TimeDiff { + match self { + Transaction::Deploy(deploy) => deploy.header().ttl(), + Transaction::V1(v1) => v1.header().ttl(), + } + } + /// Returns `Ok` if the given transaction is valid. Verification procedure is delegated to the /// implementation of the particular variant of the transaction. - pub fn verify(&self) -> Result<(), TransactionConfigFailure> { + pub fn verify(&self) -> Result<(), InvalidTransaction> { match self { Transaction::Deploy(deploy) => deploy.is_valid().map_err(Into::into), Transaction::V1(v1) => v1.verify().map_err(Into::into), @@ -304,35 +300,44 @@ impl Transaction { } } - /// Is this a native mint transaction. - pub fn is_native_mint(&self) -> bool { + /// Returns `true` if `self` represents a native transfer deploy or a native V1 transaction. + pub fn is_native(&self) -> bool { match self { Transaction::Deploy(deploy) => deploy.is_transfer(), - Transaction::V1(transaction_v1) => match transaction_v1.target() { - TransactionTarget::Stored { .. } | TransactionTarget::Session { .. } => false, - TransactionTarget::Native => { - &TransactionEntryPoint::Transfer == transaction_v1.entry_point() + Transaction::V1(v1_txn) => *v1_txn.target() == TransactionTarget::Native, + } + } + + /// Is this a transaction that should be sent to the v1 execution engine? + pub fn is_v1_wasm(&self) -> bool { + match self { + Transaction::Deploy(deploy) => !deploy.is_transfer(), + Transaction::V1(v1) => v1.is_v1_wasm(), + } + } + + /// Should this transaction use standard payment processing? + pub fn is_standard_payment(&self) -> bool { + match self { + Transaction::Deploy(deploy) => deploy.payment().is_standard_payment(Phase::Payment), + Transaction::V1(v1) => { + if let PricingMode::Classic { + standard_payment, .. + } = v1.pricing_mode() + { + *standard_payment + } else { + true } - }, + } } } - /// Is this a native auction transaction. - pub fn is_native_auction(&self) -> bool { + /// Should this transaction start in the initiating accounts context? + pub fn is_account_session(&self) -> bool { match self { - Transaction::Deploy(_) => false, - Transaction::V1(transaction_v1) => match transaction_v1.target() { - TransactionTarget::Stored { .. } | TransactionTarget::Session { .. } => false, - TransactionTarget::Native => match transaction_v1.entry_point() { - TransactionEntryPoint::Custom(_) | TransactionEntryPoint::Transfer => false, - TransactionEntryPoint::AddBid - | TransactionEntryPoint::WithdrawBid - | TransactionEntryPoint::Delegate - | TransactionEntryPoint::Undelegate - | TransactionEntryPoint::Redelegate - | TransactionEntryPoint::ActivateBid => true, - }, - }, + Transaction::Deploy(deploy) => deploy.is_account_session(), + Transaction::V1(v1) => v1.is_account_session(), } } @@ -386,6 +391,75 @@ impl Transaction { } } +/// Self discloses category. +pub trait Categorized { + /// What category does this instance belong in. + fn category(&self) -> TransactionCategory; +} + +impl Categorized for Transaction { + fn category(&self) -> TransactionCategory { + match self { + Transaction::Deploy(deploy) => deploy.category(), + Transaction::V1(v1) => v1.category(), + } + } +} + +/// Calculates gas limit. +#[cfg(any(feature = "std", test))] +pub trait GasLimited { + /// The error type. + type Error; + + /// The minimum allowed gas price (aka the floor). + const GAS_PRICE_FLOOR: u8 = 1; + + /// Returns a gas cost based upon the gas_limit, the gas price, + /// and the chainspec settings. + fn gas_cost(&self, chainspec: &Chainspec, gas_price: u8) -> Result; + + /// Returns the gas / computation limit prior to execution. + fn gas_limit(&self, chainspec: &Chainspec) -> Result; + + /// Returns the gas price tolerance. + fn gas_price_tolerance(&self) -> Result; +} + +#[cfg(any(feature = "std", test))] +impl GasLimited for Transaction { + type Error = InvalidTransaction; + + fn gas_cost(&self, chainspec: &Chainspec, gas_price: u8) -> Result { + match self { + Transaction::Deploy(deploy) => deploy + .gas_cost(chainspec, gas_price) + .map_err(InvalidTransaction::from), + Transaction::V1(v1) => v1 + .gas_cost(chainspec, gas_price) + .map_err(InvalidTransaction::from), + } + } + + fn gas_limit(&self, chainspec: &Chainspec) -> Result { + match self { + Transaction::Deploy(deploy) => deploy + .gas_limit(chainspec) + .map_err(InvalidTransaction::from), + Transaction::V1(v1) => v1.gas_limit(chainspec).map_err(InvalidTransaction::from), + } + } + + fn gas_price_tolerance(&self) -> Result { + match self { + Transaction::Deploy(deploy) => deploy + .gas_price_tolerance() + .map_err(InvalidTransaction::from), + Transaction::V1(v1) => v1.gas_price_tolerance().map_err(InvalidTransaction::from), + } + } +} + impl From for Transaction { fn from(deploy: Deploy) -> Self { Self::Deploy(deploy) @@ -399,19 +473,6 @@ impl From for Transaction { } impl ToBytes for Transaction { - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - match self { - Transaction::Deploy(deploy) => { - DEPLOY_TAG.write_bytes(writer)?; - deploy.write_bytes(writer) - } - Transaction::V1(txn) => { - V1_TAG.write_bytes(writer)?; - txn.write_bytes(writer) - } - } - } - fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; @@ -425,6 +486,19 @@ impl ToBytes for Transaction { Transaction::V1(txn) => txn.serialized_length(), } } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + match self { + Transaction::Deploy(deploy) => { + DEPLOY_TAG.write_bytes(writer)?; + deploy.write_bytes(writer) + } + Transaction::V1(txn) => { + V1_TAG.write_bytes(writer)?; + txn.write_bytes(writer) + } + } + } } impl FromBytes for Transaction { @@ -453,6 +527,21 @@ impl Display for Transaction { } } +/// Proptest generators for [`Transaction`]. +#[cfg(any(feature = "testing", feature = "gens", test))] +pub mod gens { + use proptest::{ + array, + prelude::{Arbitrary, Strategy}, + }; + + use super::*; + + pub fn deploy_hash_arb() -> impl Strategy { + array::uniform32(::arbitrary()).prop_map(DeployHash::from_raw) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/types/src/transaction/addressable_entity_identifier.rs b/types/src/transaction/addressable_entity_identifier.rs index bf588473f0..9fee6fad72 100644 --- a/types/src/transaction/addressable_entity_identifier.rs +++ b/types/src/transaction/addressable_entity_identifier.rs @@ -15,11 +15,12 @@ use super::{ExecutableDeployItem, TransactionTarget}; use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, - AddressableEntityHash, + AddressableEntityHash, EntityAddr, }; const HASH_TAG: u8 = 0; const NAME_TAG: u8 = 1; +const ADDR_TAG: u8 = 2; /// Identifier for the contract object within a [`TransactionTarget::Stored`] or an /// [`ExecutableDeployItem`]. @@ -39,6 +40,8 @@ pub enum AddressableEntityIdentifier { Hash(AddressableEntityHash), /// The name identifying the addressable entity. Name(String), + /// The entity address + Addr(EntityAddr), } impl AddressableEntityIdentifier { @@ -46,7 +49,11 @@ impl AddressableEntityIdentifier { #[cfg(any(feature = "testing", test))] pub fn random(rng: &mut TestRng) -> Self { if rng.gen() { - AddressableEntityIdentifier::Hash(AddressableEntityHash::new(rng.gen())) + if rng.gen() { + AddressableEntityIdentifier::Hash(AddressableEntityHash::new(rng.gen())) + } else { + AddressableEntityIdentifier::Addr(EntityAddr::new_of_kind(rng.gen(), rng.gen())) + } } else { AddressableEntityIdentifier::Name(rng.random_string(1..21)) } @@ -58,6 +65,9 @@ impl Display for AddressableEntityIdentifier { match self { AddressableEntityIdentifier::Hash(hash) => write!(formatter, "entity-hash({})", hash), AddressableEntityIdentifier::Name(name) => write!(formatter, "entity-name({})", name), + AddressableEntityIdentifier::Addr(entity_addr) => { + write!(formatter, "entity-addr({})", entity_addr) + } } } } @@ -73,6 +83,10 @@ impl ToBytes for AddressableEntityIdentifier { NAME_TAG.write_bytes(writer)?; name.write_bytes(writer) } + AddressableEntityIdentifier::Addr(entity_addr) => { + ADDR_TAG.write_bytes(writer)?; + entity_addr.write_bytes(writer) + } } } @@ -87,6 +101,7 @@ impl ToBytes for AddressableEntityIdentifier { + match self { AddressableEntityIdentifier::Hash(hash) => hash.serialized_length(), AddressableEntityIdentifier::Name(name) => name.serialized_length(), + AddressableEntityIdentifier::Addr(addr) => addr.serialized_length(), } } } @@ -103,6 +118,10 @@ impl FromBytes for AddressableEntityIdentifier { let (name, remainder) = String::from_bytes(remainder)?; Ok((AddressableEntityIdentifier::Name(name), remainder)) } + ADDR_TAG => { + let (addr, remainder) = EntityAddr::from_bytes(remainder)?; + Ok((AddressableEntityIdentifier::Addr(addr), remainder)) + } _ => Err(bytesrepr::Error::Formatting), } } diff --git a/types/src/transaction/deploy.rs b/types/src/transaction/deploy.rs index b082150c47..78eb6d3bf2 100644 --- a/types/src/transaction/deploy.rs +++ b/types/src/transaction/deploy.rs @@ -14,37 +14,28 @@ use core::{ hash, }; +#[cfg(any(feature = "std", test))] +use std::convert::TryFrom; + #[cfg(feature = "datasize")] use datasize::DataSize; +#[cfg(any(feature = "std", test))] +use itertools::Itertools; +#[cfg(feature = "json-schema")] +use once_cell::sync::Lazy; #[cfg(any(feature = "once_cell", test))] use once_cell::sync::OnceCell; -#[cfg(any(feature = "std", test))] -use { - super::{InitiatorAddr, InitiatorAddrAndSecretKey}, - crate::Gas, - crate::Motes, - crate::U512, - itertools::Itertools, - serde::{Deserialize, Serialize}, -}; #[cfg(any(all(feature = "std", feature = "testing"), test))] -use { - crate::{ - bytesrepr::Bytes, - system::auction::{ - ARG_AMOUNT as ARG_AUCTION_AMOUNT, ARG_DELEGATOR, ARG_NEW_VALIDATOR, - ARG_PUBLIC_KEY as ARG_AUCTION_PUBLIC_KEY, ARG_VALIDATOR, METHOD_DELEGATE, - METHOD_REDELEGATE, METHOD_UNDELEGATE, METHOD_WITHDRAW_BID, - }, - AddressableEntityHash, TransactionConfig, - {testing::TestRng, DEFAULT_MAX_PAYMENT_MOTES, DEFAULT_MIN_TRANSFER_MOTES}, - }, - rand::Rng, - tracing::{debug, warn}, -}; +use rand::Rng; #[cfg(feature = "json-schema")] -use {once_cell::sync::Lazy, schemars::JsonSchema}; +use schemars::JsonSchema; +#[cfg(any(feature = "std", test))] +use serde::{Deserialize, Serialize}; +#[cfg(any(all(feature = "std", feature = "testing"), test))] +use tracing::{debug, warn}; +#[cfg(any(feature = "std", test))] +use super::{InitiatorAddr, InitiatorAddrAndSecretKey}; #[cfg(any( all(feature = "std", feature = "testing"), feature = "json-schema", @@ -52,16 +43,27 @@ use {once_cell::sync::Lazy, schemars::JsonSchema}; ))] use crate::runtime_args; #[cfg(any(all(feature = "std", feature = "testing"), test))] -use crate::RuntimeArgs; +use crate::{ + bytesrepr::Bytes, + system::auction::{ + ARG_AMOUNT as ARG_AUCTION_AMOUNT, ARG_DELEGATOR, ARG_NEW_VALIDATOR, + ARG_PUBLIC_KEY as ARG_AUCTION_PUBLIC_KEY, ARG_VALIDATOR, METHOD_DELEGATE, + METHOD_REDELEGATE, METHOD_UNDELEGATE, METHOD_WITHDRAW_BID, + }, + testing::TestRng, + AddressableEntityHash, RuntimeArgs, DEFAULT_MAX_PAYMENT_MOTES, DEFAULT_MIN_TRANSFER_MOTES, +}; use crate::{ bytesrepr::{self, FromBytes, ToBytes}, - crypto, Digest, DisplayIter, PublicKey, SecretKey, TimeDiff, Timestamp, + crypto, + transaction::{Approval, ApprovalsHash, Categorized}, + Digest, DisplayIter, PublicKey, SecretKey, TimeDiff, Timestamp, TransactionCategory, }; #[cfg(any(feature = "std", test))] -use crate::{system::auction::ARG_AMOUNT, SystemConfig}; - -use crate::transaction::{Approval, ApprovalsHash}; +use crate::{chainspec::PricingHandling, Chainspec}; +#[cfg(any(feature = "std", test))] +use crate::{system::auction::ARG_AMOUNT, transaction::GasLimited, Gas, Motes, U512}; #[cfg(any(feature = "std", test))] pub use deploy_builder::{DeployBuilder, DeployBuilderError}; pub use deploy_category::DeployCategory; @@ -69,12 +71,10 @@ pub use deploy_hash::DeployHash; pub use deploy_header::DeployHeader; pub use deploy_id::DeployId; pub use error::{ - DecodeFromJsonError as DeployDecodeFromJsonError, DeployConfigFailure, Error as DeployError, - ExcessiveSizeError as DeployExcessiveSizeError, -}; -pub use executable_deploy_item::{ - ExecutableDeployItem, ExecutableDeployItemIdentifier, TransferTarget, + DecodeFromJsonError as DeployDecodeFromJsonError, Error as DeployError, + ExcessiveSizeError as DeployExcessiveSizeError, InvalidDeploy, }; +pub use executable_deploy_item::{ExecutableDeployItem, ExecutableDeployItemIdentifier}; #[cfg(feature = "json-schema")] static DEPLOY: Lazy = Lazy::new(|| { @@ -148,7 +148,7 @@ pub struct Deploy { data_size(skip) )] #[cfg(any(feature = "once_cell", test))] - is_valid: OnceCell>, + is_valid: OnceCell>, } impl Deploy { @@ -263,7 +263,7 @@ impl Deploy { self.header.expired(current_instant) } - /// Returns the price per gas unit for the `Deploy`. + /// Returns the sender's gas price tolerance for block inclusion. pub fn gas_price(&self) -> u64 { self.header.gas_price() } @@ -303,6 +303,25 @@ impl Deploy { &self.approvals } + /// Consumes `self`, returning a tuple of its constituent parts. + pub fn destructure( + self, + ) -> ( + DeployHash, + DeployHeader, + ExecutableDeployItem, + ExecutableDeployItem, + BTreeSet, + ) { + ( + self.hash, + self.header, + self.payment, + self.session, + self.approvals, + ) + } + /// Adds a signature of this `Deploy`'s hash to its approvals. pub fn sign(&mut self, secret_key: &SecretKey) { let approval = Approval::create(&self.hash.into(), secret_key); @@ -330,13 +349,13 @@ impl Deploy { /// Returns `Ok` if and only if this `Deploy`'s body hashes to the value of `body_hash()`, and /// if this `Deploy`'s header hashes to the value claimed as the deploy hash. - pub fn has_valid_hash(&self) -> Result<(), DeployConfigFailure> { + pub fn has_valid_hash(&self) -> Result<(), InvalidDeploy> { let serialized_body = serialize_body(&self.payment, &self.session); let body_hash = Digest::hash(serialized_body); if body_hash != *self.header.body_hash() { #[cfg(any(all(feature = "std", feature = "testing"), test))] warn!(?self, ?body_hash, "invalid deploy body hash"); - return Err(DeployConfigFailure::InvalidBodyHash); + return Err(InvalidDeploy::InvalidBodyHash); } let serialized_header = serialize_header(&self.header); @@ -344,7 +363,7 @@ impl Deploy { if hash != self.hash { #[cfg(any(all(feature = "std", feature = "testing"), test))] warn!(?self, ?hash, "invalid deploy hash"); - return Err(DeployConfigFailure::InvalidDeployHash); + return Err(InvalidDeploy::InvalidDeployHash); } Ok(()) } @@ -354,7 +373,7 @@ impl Deploy { /// * the body hash is correct (should be the hash of the body), and /// * approvals are non empty, and /// * all approvals are valid signatures of the deploy hash - pub fn is_valid(&self) -> Result<(), DeployConfigFailure> { + pub fn is_valid(&self) -> Result<(), InvalidDeploy> { #[cfg(any(feature = "once_cell", test))] return self.is_valid.get_or_init(|| validate_deploy(self)).clone(); @@ -367,38 +386,10 @@ impl Deploy { self.session.is_transfer() } - /// Gas limit. - #[cfg(any(feature = "std", test))] - pub fn gas_limit( - &self, - system_costs: &SystemConfig, - gas_price: Option, - ) -> Result { - let user_specified_price = self.gas_price(); - let actual_price = match gas_price { - Some(price) => price.max(user_specified_price), - None => user_specified_price, - }; - let motes = { - if self.is_transfer() { - Motes::new(U512::from(system_costs.mint_costs().transfer)) - } else { - let value = self - .payment() - .args() - .get(ARG_AMOUNT) - .ok_or(DeployConfigFailure::MissingPaymentAmount)?; - let payment_amount = value - .clone() - .into_t::() - .map_err(|_| DeployConfigFailure::FailedToParsePaymentAmount)?; - Motes::new(payment_amount) - } - }; - match Gas::from_motes(motes, actual_price) { - Some(gas) => Ok(gas), - None => Err(DeployConfigFailure::MissingPaymentAmount), - } + /// Should this transaction start in the initiating accounts context? + pub fn is_account_session(&self) -> bool { + // legacy deploys are always initiated by an account + true } /// Returns `Ok` if and only if: @@ -407,16 +398,15 @@ impl Deploy { #[cfg(any(all(feature = "std", feature = "testing"), test))] pub fn is_config_compliant( &self, - chain_name: &str, - cost_table: &SystemConfig, - config: &TransactionConfig, - max_associated_keys: u32, + chainspec: &Chainspec, timestamp_leeway: TimeDiff, at: Timestamp, - ) -> Result<(), DeployConfigFailure> { + ) -> Result<(), InvalidDeploy> { + let config = &chainspec.transaction_config; self.is_valid_size(config.max_transaction_size)?; let header = self.header(); + let chain_name = &chainspec.network_config.name; if header.chain_name() != chain_name { debug!( deploy_hash = %self.hash(), @@ -424,7 +414,7 @@ impl Deploy { chain_name = %header.chain_name(), "invalid chain identifier" ); - return Err(DeployConfigFailure::InvalidChainName { + return Err(InvalidDeploy::InvalidChainName { expected: chain_name.to_string(), got: header.chain_name().to_string(), }); @@ -432,6 +422,7 @@ impl Deploy { header.is_valid(config, timestamp_leeway, at, &self.hash)?; + let max_associated_keys = chainspec.core_config.max_associated_keys; if self.approvals.len() > max_associated_keys as usize { debug!( deploy_hash = %self.hash(), @@ -439,21 +430,21 @@ impl Deploy { max_associated_keys = %max_associated_keys, "number of associated keys exceeds the maximum limit" ); - return Err(DeployConfigFailure::ExcessiveApprovals { + return Err(InvalidDeploy::ExcessiveApprovals { got: self.approvals.len() as u32, max_associated_keys, }); } - let gas_limit = self.gas_limit(cost_table, None)?; - let block_gas_limit = Gas::new(U512::from(config.block_gas_limit)); + let gas_limit = self.gas_limit(chainspec)?; + let block_gas_limit = Gas::new(config.block_gas_limit); if gas_limit > block_gas_limit { debug!( payment_amount = %gas_limit, %block_gas_limit, "transaction gas limit exceeds block gas limit" ); - return Err(DeployConfigFailure::ExceededBlockGasLimit { + return Err(InvalidDeploy::ExceededBlockGasLimit { block_gas_limit: config.block_gas_limit, got: Box::new(gas_limit.value()), }); @@ -466,7 +457,7 @@ impl Deploy { payment_args_max_length = config.deploy_config.payment_args_max_length, "payment args excessive" ); - return Err(DeployConfigFailure::ExcessivePaymentArgsLength { + return Err(InvalidDeploy::ExcessivePaymentArgsLength { max_length: config.deploy_config.payment_args_max_length as usize, got: payment_args_length, }); @@ -479,7 +470,7 @@ impl Deploy { session_args_max_length = config.deploy_config.session_args_max_length, "session args excessive" ); - return Err(DeployConfigFailure::ExcessiveSessionArgsLength { + return Err(InvalidDeploy::ExcessiveSessionArgsLength { max_length: config.deploy_config.session_args_max_length as usize, got: session_args_length, }); @@ -492,13 +483,13 @@ impl Deploy { .get(ARG_AMOUNT) .ok_or_else(|| { debug!("missing transfer 'amount' runtime argument"); - DeployConfigFailure::MissingTransferAmount + InvalidDeploy::MissingTransferAmount })? .clone() .into_t::() .map_err(|_| { debug!("failed to parse transfer 'amount' runtime argument as a U512"); - DeployConfigFailure::FailedToParseTransferAmount + InvalidDeploy::FailedToParseTransferAmount })?; let minimum = U512::from(config.native_transfer_minimum_motes); if attempted < minimum { @@ -507,7 +498,7 @@ impl Deploy { amount = %attempted, "insufficient transfer amount" ); - return Err(DeployConfigFailure::InsufficientTransferAmount { + return Err(InvalidDeploy::InsufficientTransferAmount { minimum: Box::new(minimum), attempted: Box::new(attempted), }); @@ -1156,6 +1147,67 @@ impl Deploy { } } +impl Categorized for Deploy { + fn category(&self) -> TransactionCategory { + if self.is_transfer() { + TransactionCategory::Mint + } else { + TransactionCategory::Standard + } + } +} + +#[cfg(any(feature = "std", test))] +impl GasLimited for Deploy { + type Error = InvalidDeploy; + + fn gas_cost(&self, chainspec: &Chainspec, gas_price: u8) -> Result { + let gas_limit = self.gas_limit(chainspec)?; + let motes = + Motes::from_gas(gas_limit, gas_price).ok_or(InvalidDeploy::UnableToCalculateGasCost)?; + Ok(motes) + } + + fn gas_limit(&self, chainspec: &Chainspec) -> Result { + let pricing_handling = chainspec.core_config.pricing_handling; + let costs = &chainspec.system_costs_config; + let gas_limit = match pricing_handling { + PricingHandling::Classic => { + // in the original implementation, for standard deploys the payment amount + // specified by the sender is the gas limit (up to the max block limit). + if self.is_transfer() { + Gas::new(costs.mint_costs().transfer) + } else { + let value = self + .payment() + .args() + .get(ARG_AMOUNT) + .ok_or(InvalidDeploy::MissingPaymentAmount)?; + let payment_amount = value + .clone() + .into_t::() + .map_err(|_| InvalidDeploy::FailedToParsePaymentAmount)?; + Gas::new(payment_amount) + } + } + PricingHandling::Fixed => { + // in fixed, the computation limit is fixed per the chainspec settings + let computation_limit = if self.is_transfer() { + costs.mint_costs().transfer as u64 + } else { + costs.standard_transaction_limit() + }; + Gas::new(computation_limit) + } // legacy deploys do not support reservations + }; + Ok(gas_limit) + } + + fn gas_price_tolerance(&self) -> Result { + u8::try_from(self.gas_price()).map_err(|_| Self::Error::UnableToCalculateGasLimit) + } +} + impl hash::Hash for Deploy { fn hash(&self, state: &mut H) { // Destructure to make sure we don't accidentally omit fields. @@ -1247,14 +1299,6 @@ impl PartialOrd for Deploy { } impl ToBytes for Deploy { - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - self.header.write_bytes(writer)?; - self.hash.write_bytes(writer)?; - self.payment.write_bytes(writer)?; - self.session.write_bytes(writer)?; - self.approvals.write_bytes(writer) - } - fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; @@ -1268,6 +1312,14 @@ impl ToBytes for Deploy { + self.session.serialized_length() + self.approvals.serialized_length() } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.header.write_bytes(writer)?; + self.hash.write_bytes(writer)?; + self.payment.write_bytes(writer)?; + self.session.write_bytes(writer)?; + self.approvals.write_bytes(writer) + } } impl FromBytes for Deploy { @@ -1323,11 +1375,11 @@ fn serialize_body(payment: &ExecutableDeployItem, session: &ExecutableDeployItem /// Computationally expensive validity check for a given deploy instance, including asymmetric_key /// signing verification. -fn validate_deploy(deploy: &Deploy) -> Result<(), DeployConfigFailure> { +fn validate_deploy(deploy: &Deploy) -> Result<(), InvalidDeploy> { if deploy.approvals.is_empty() { #[cfg(any(all(feature = "std", feature = "testing"), test))] warn!(?deploy, "deploy has no approvals"); - return Err(DeployConfigFailure::EmptyApprovals); + return Err(InvalidDeploy::EmptyApprovals); } deploy.has_valid_hash()?; @@ -1336,7 +1388,7 @@ fn validate_deploy(deploy: &Deploy) -> Result<(), DeployConfigFailure> { if let Err(error) = crypto::verify(deploy.hash, approval.signature(), approval.signer()) { #[cfg(any(all(feature = "std", feature = "testing"), test))] warn!(?deploy, "failed to verify approval {}: {}", index, error); - return Err(DeployConfigFailure::InvalidApproval { index, error }); + return Err(InvalidDeploy::InvalidApproval { index, error }); } } @@ -1348,9 +1400,7 @@ mod tests { use std::{iter, time::Duration}; use super::*; - use crate::CLValue; - - const DEFAULT_MAX_ASSOCIATED_KEYS: u32 = 100; + use crate::{CLValue, TransactionConfig}; #[test] fn json_roundtrip() { @@ -1416,6 +1466,7 @@ mod tests { #[test] fn is_valid() { let mut rng = TestRng::new(); + let deploy = create_deploy(&mut rng, TransactionConfig::default().max_ttl, 0, "net-1"); assert_eq!( deploy.is_valid.get(), @@ -1430,7 +1481,7 @@ mod tests { ); } - fn check_is_not_valid(invalid_deploy: Deploy, expected_error: DeployConfigFailure) { + fn check_is_not_valid(invalid_deploy: Deploy, expected_error: InvalidDeploy) { assert!( invalid_deploy.is_valid.get().is_none(), "is valid should initially be None" @@ -1441,11 +1492,11 @@ mod tests { // this makes the test too fragile. Otherwise expect the actual error should exactly match // the expected error. match expected_error { - DeployConfigFailure::InvalidApproval { + InvalidDeploy::InvalidApproval { index: expected_index, .. } => match actual_error { - DeployConfigFailure::InvalidApproval { + InvalidDeploy::InvalidApproval { index: actual_index, .. } => { @@ -1476,7 +1527,7 @@ mod tests { "amount" => 1 }, }; - check_is_not_valid(deploy, DeployConfigFailure::InvalidBodyHash); + check_is_not_valid(deploy, InvalidDeploy::InvalidBodyHash); } #[test] @@ -1486,7 +1537,7 @@ mod tests { // deploy.header.gas_price = 2; deploy.invalidate(); - check_is_not_valid(deploy, DeployConfigFailure::InvalidDeployHash); + check_is_not_valid(deploy, InvalidDeploy::InvalidDeployHash); } #[test] @@ -1495,7 +1546,7 @@ mod tests { let mut deploy = create_deploy(&mut rng, TransactionConfig::default().max_ttl, 0, "net-1"); deploy.approvals = BTreeSet::new(); assert!(deploy.approvals.is_empty()); - check_is_not_valid(deploy, DeployConfigFailure::EmptyApprovals) + check_is_not_valid(deploy, InvalidDeploy::EmptyApprovals) } #[test] @@ -1517,7 +1568,7 @@ mod tests { .unwrap(); check_is_not_valid( deploy, - DeployConfigFailure::InvalidApproval { + InvalidDeploy::InvalidApproval { index: expected_index, error: crypto::Error::SignatureError, // This field is ignored in the check. }, @@ -1527,26 +1578,20 @@ mod tests { #[test] fn is_acceptable() { let mut rng = TestRng::new(); - let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + let chain_name = "net-1".to_string(); + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let deploy = create_deploy( &mut rng, config.max_ttl, config.deploy_config.max_dependencies.into(), - chain_name, + &chain_name, ); let current_timestamp = deploy.header().timestamp(); deploy - .is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp, - ) + .is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) .expect("should be acceptable"); } @@ -1555,8 +1600,10 @@ mod tests { let mut rng = TestRng::new(); let expected_chain_name = "net-1"; let wrong_chain_name = "net-2".to_string(); - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(expected_chain_name.to_string()); + let config = chainspec.transaction_config; let deploy = create_deploy( &mut rng, @@ -1565,21 +1612,14 @@ mod tests { &wrong_chain_name, ); - let expected_error = DeployConfigFailure::InvalidChainName { + let expected_error = InvalidDeploy::InvalidChainName { expected: expected_chain_name.to_string(), got: wrong_chain_name, }; let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - expected_chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), Err(expected_error) ); assert!( @@ -1592,25 +1632,20 @@ mod tests { fn not_acceptable_due_to_excessive_dependencies() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let dependency_count = usize::from(config.deploy_config.max_dependencies + 1); let deploy = create_deploy(&mut rng, config.max_ttl, dependency_count, chain_name); - let expected_error = DeployConfigFailure::DependenciesNoLongerSupported; + let expected_error = InvalidDeploy::DependenciesNoLongerSupported; let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), Err(expected_error) ); assert!( @@ -1623,8 +1658,10 @@ mod tests { fn not_acceptable_due_to_excessive_ttl() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let ttl = config.max_ttl + TimeDiff::from(Duration::from_secs(1)); @@ -1635,21 +1672,14 @@ mod tests { chain_name, ); - let expected_error = DeployConfigFailure::ExcessiveTimeToLive { + let expected_error = InvalidDeploy::ExcessiveTimeToLive { max_ttl: config.max_ttl, got: ttl, }; let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), Err(expected_error) ); assert!( @@ -1662,8 +1692,10 @@ mod tests { fn not_acceptable_due_to_timestamp_in_future() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let leeway = TimeDiff::from_seconds(2); let deploy = create_deploy( @@ -1674,21 +1706,14 @@ mod tests { ); let current_timestamp = deploy.header.timestamp() - leeway - TimeDiff::from_seconds(1); - let expected_error = DeployConfigFailure::TimestampInFuture { + let expected_error = InvalidDeploy::TimestampInFuture { validation_timestamp: current_timestamp, timestamp_leeway: leeway, got: deploy.header.timestamp(), }; assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - leeway, - current_timestamp - ), + deploy.is_config_compliant(&chainspec, leeway, current_timestamp), Err(expected_error) ); assert!( @@ -1701,8 +1726,10 @@ mod tests { fn acceptable_if_timestamp_slightly_in_future() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let leeway = TimeDiff::from_seconds(2); let deploy = create_deploy( @@ -1713,14 +1740,7 @@ mod tests { ); let current_timestamp = deploy.header.timestamp() - (leeway / 2); deploy - .is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - leeway, - current_timestamp, - ) + .is_config_compliant(&chainspec, leeway, current_timestamp) .expect("should be acceptable"); } @@ -1728,8 +1748,11 @@ mod tests { fn not_acceptable_due_to_missing_payment_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + chainspec.with_pricing_handling(PricingHandling::Classic); + let config = chainspec.transaction_config; let payment = ExecutableDeployItem::ModuleBytes { module_bytes: Bytes::new(), @@ -1756,15 +1779,8 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), - Err(DeployConfigFailure::MissingPaymentAmount) + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), + Err(InvalidDeploy::MissingPaymentAmount) ); assert!( deploy.is_valid.get().is_none(), @@ -1776,8 +1792,11 @@ mod tests { fn not_acceptable_due_to_mangled_payment_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + chainspec.with_pricing_handling(PricingHandling::Classic); + let config = chainspec.transaction_config; let payment = ExecutableDeployItem::ModuleBytes { module_bytes: Bytes::new(), @@ -1806,15 +1825,8 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), - Err(DeployConfigFailure::FailedToParsePaymentAmount) + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), + Err(InvalidDeploy::FailedToParsePaymentAmount) ); assert!( deploy.is_valid.get().is_none(), @@ -1826,8 +1838,11 @@ mod tests { fn not_acceptable_due_to_excessive_payment_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + chainspec.with_pricing_handling(PricingHandling::Classic); + let config = chainspec.transaction_config; let amount = U512::from(config.block_gas_limit + 1); let payment = ExecutableDeployItem::ModuleBytes { @@ -1855,21 +1870,14 @@ mod tests { deploy.payment = payment; deploy.session = session; - let expected_error = DeployConfigFailure::ExceededBlockGasLimit { + let expected_error = InvalidDeploy::ExceededBlockGasLimit { block_gas_limit: config.block_gas_limit, got: Box::new(amount), }; let current_timestamp = deploy.header().timestamp(); assert_eq!( - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp), Err(expected_error) ); assert!( @@ -1883,8 +1891,10 @@ mod tests { let mut rng = TestRng::new(); let secret_key = SecretKey::random(&mut rng); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let amount = U512::from(config.block_gas_limit + 1); let payment = ExecutableDeployItem::ModuleBytes { @@ -1919,14 +1929,7 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( Ok(()), - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ) + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) ) } @@ -1934,8 +1937,10 @@ mod tests { fn not_acceptable_due_to_excessive_approvals() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + let config = chainspec.transaction_config; let deploy = create_deploy( &mut rng, config.max_ttl, @@ -1945,20 +1950,14 @@ mod tests { // This test is to ensure a given limit is being checked. // Therefore, set the limit to one less than the approvals in the deploy. let max_associated_keys = (deploy.approvals.len() - 1) as u32; + chainspec.with_max_associated_keys(max_associated_keys); let current_timestamp = deploy.header().timestamp(); assert_eq!( - Err(DeployConfigFailure::ExcessiveApprovals { + Err(InvalidDeploy::ExcessiveApprovals { got: deploy.approvals.len() as u32, - max_associated_keys: (deploy.approvals.len() - 1) as u32 + max_associated_keys }), - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - max_associated_keys, - TimeDiff::default(), - current_timestamp - ) + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) ) } @@ -1966,8 +1965,10 @@ mod tests { fn not_acceptable_due_to_missing_transfer_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + + let config = chainspec.transaction_config; let mut deploy = create_deploy( &mut rng, config.max_ttl, @@ -1983,15 +1984,8 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( - Err(DeployConfigFailure::MissingTransferAmount), - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ) + Err(InvalidDeploy::MissingTransferAmount), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) ) } @@ -1999,8 +1993,10 @@ mod tests { fn not_acceptable_due_to_mangled_transfer_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + + let config = chainspec.transaction_config; let mut deploy = create_deploy( &mut rng, config.max_ttl, @@ -2020,15 +2016,8 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( - Err(DeployConfigFailure::FailedToParseTransferAmount), - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ) + Err(InvalidDeploy::FailedToParseTransferAmount), + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) ) } @@ -2036,8 +2025,10 @@ mod tests { fn not_acceptable_due_to_insufficient_transfer_amount() { let mut rng = TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let config = TransactionConfig::default(); + let mut chainspec = Chainspec::default(); + chainspec.with_chain_name(chain_name.to_string()); + + let config = chainspec.transaction_config; let mut deploy = create_deploy( &mut rng, config.max_ttl, @@ -2060,18 +2051,127 @@ mod tests { let current_timestamp = deploy.header().timestamp(); assert_eq!( - Err(DeployConfigFailure::InsufficientTransferAmount { + Err(InvalidDeploy::InsufficientTransferAmount { minimum: Box::new(U512::from(config.native_transfer_minimum_motes)), attempted: Box::new(insufficient_amount), }), - deploy.is_config_compliant( - chain_name, - &cost_table, - &config, - DEFAULT_MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ) + deploy.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) ) } + + #[test] + fn should_use_payment_amount_for_classic_payment() { + let payment_amount = 500u64; + let mut rng = TestRng::new(); + let chain_name = "net-1"; + let mut chainspec = Chainspec::default(); + chainspec + .with_chain_name(chain_name.to_string()) + .with_pricing_handling(PricingHandling::Classic); + + let config = chainspec.transaction_config; + + let payment = ExecutableDeployItem::ModuleBytes { + module_bytes: Bytes::new(), + args: runtime_args! { + "amount" => U512::from(payment_amount) + }, + }; + + // Create an empty session object that is not transfer to ensure + // that the payment amount is checked. + let session = ExecutableDeployItem::StoredContractByName { + name: "".to_string(), + entry_point: "".to_string(), + args: Default::default(), + }; + + let mut deploy = create_deploy( + &mut rng, + config.max_ttl, + config.deploy_config.max_dependencies.into(), + chain_name, + ); + deploy.payment = payment; + deploy.session = session; + + let mut gas_price = 1; + let cost = deploy + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::from(payment_amount), + "in classic pricing, the user selected amount should be the cost if gas price is 1" + ); + gas_price += 1; + let cost = deploy + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::from(payment_amount) * gas_price, + "in classic pricing, the cost should == user selected amount * gas_price" + ); + } + + #[test] + fn should_use_cost_table_for_fixed_payment() { + let payment_amount = 500u64; + let mut rng = TestRng::new(); + let chain_name = "net-1"; + let mut chainspec = Chainspec::default(); + chainspec + .with_chain_name(chain_name.to_string()) + .with_pricing_handling(PricingHandling::Classic); + + let config = chainspec.transaction_config; + + let payment = ExecutableDeployItem::ModuleBytes { + module_bytes: Bytes::new(), + args: runtime_args! { + "amount" => U512::from(payment_amount) + }, + }; + + // Create an empty session object that is not transfer to ensure + // that the payment amount is checked. + let session = ExecutableDeployItem::StoredContractByName { + name: "".to_string(), + entry_point: "".to_string(), + args: Default::default(), + }; + + let mut deploy = create_deploy( + &mut rng, + config.max_ttl, + config.deploy_config.max_dependencies.into(), + chain_name, + ); + deploy.payment = payment; + deploy.session = session; + + let mut gas_price = 1; + let limit = deploy.gas_limit(&chainspec).expect("should limit").value(); + let cost = deploy + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, limit, + "in fixed pricing, the cost & limit should == if gas price is 1" + ); + gas_price += 1; + let cost = deploy + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + limit * gas_price, + "in fixed pricing, the cost should == limit * gas_price" + ); + } } diff --git a/types/src/transaction/deploy/deploy_builder.rs b/types/src/transaction/deploy/deploy_builder.rs index 7c79e0defa..b2c7c021e8 100644 --- a/types/src/transaction/deploy/deploy_builder.rs +++ b/types/src/transaction/deploy/deploy_builder.rs @@ -1,8 +1,8 @@ mod error; use super::{ - super::{InitiatorAddr, InitiatorAddrAndSecretKey}, - Deploy, DeployHash, ExecutableDeployItem, TransferTarget, + super::{InitiatorAddr, InitiatorAddrAndSecretKey, TransferTarget}, + Deploy, DeployHash, ExecutableDeployItem, }; use crate::{PublicKey, SecretKey, TimeDiff, Timestamp, URef, U512}; pub use error::DeployBuilderError; @@ -62,11 +62,11 @@ impl<'a> DeployBuilder<'a> { /// * that payment code is provided by either calling /// [`with_standard_payment`](Self::with_standard_payment) or /// [`with_payment`](Self::with_payment) - pub fn new_transfer, A: Into>( + pub fn new_transfer, A: Into, T: Into>( chain_name: C, amount: A, maybe_source: Option, - target: TransferTarget, + target: T, maybe_transfer_id: Option, ) -> Self { let session = diff --git a/types/src/transaction/deploy/deploy_header.rs b/types/src/transaction/deploy/deploy_header.rs index 5c78e4e964..09a27057cc 100644 --- a/types/src/transaction/deploy/deploy_header.rs +++ b/types/src/transaction/deploy/deploy_header.rs @@ -18,7 +18,7 @@ use crate::{ Digest, DisplayIter, PublicKey, TimeDiff, Timestamp, }; #[cfg(any(feature = "std", test))] -use crate::{DeployConfigFailure, TransactionConfig}; +use crate::{InvalidDeploy, TransactionConfig}; /// The header portion of a [`Deploy`]. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] @@ -83,8 +83,25 @@ impl DeployHeader { self.expires() < current_instant } - /// Returns the price per gas unit for the `Deploy`. + /// Returns the sender's gas price tolerance for block inclusion. pub fn gas_price(&self) -> u64 { + // in the original implementation, we did not have dynamic gas pricing + // but the sender of the deploy could specify a higher gas price, + // and the payment amount would be multiplied by that number + // for settlement purposes. This did not increase their computation limit, + // only how much they were charged. The intent was, the total cost + // would be a consideration for block proposal but in the end we shipped + // with an egalitarian subjective fifo proposer. Thus, there was no + // functional reason / no benefit to a sender setting gas price to + // anything higher than 1. + // + // As of 2.0 we have dynamic gas prices, this vestigial field has been + // repurposed, interpreted to indicate a gas price tolerance. + // If this deploy is buffered and the current gas price is higher than this + // value, it will not be included in a proposed block. + // + // This allowing the sender to opt out of block inclusion if the gas price is + // higher than they want to pay for. self.gas_price } @@ -112,7 +129,7 @@ impl DeployHeader { timestamp_leeway: TimeDiff, at: Timestamp, deploy_hash: &DeployHash, - ) -> Result<(), DeployConfigFailure> { + ) -> Result<(), InvalidDeploy> { // as of 2.0.0 deploy dependencies are not supported. // a legacy deploy citing dependencies should be rejected if !self.dependencies.is_empty() { @@ -120,7 +137,7 @@ impl DeployHeader { %deploy_hash, "deploy dependencies no longer supported" ); - return Err(DeployConfigFailure::DependenciesNoLongerSupported); + return Err(InvalidDeploy::DependenciesNoLongerSupported); } if self.ttl() > config.max_ttl { @@ -130,7 +147,7 @@ impl DeployHeader { max_ttl = %config.max_ttl, "deploy ttl excessive" ); - return Err(DeployConfigFailure::ExcessiveTimeToLive { + return Err(InvalidDeploy::ExcessiveTimeToLive { max_ttl: config.max_ttl, got: self.ttl(), }); @@ -138,7 +155,7 @@ impl DeployHeader { if self.timestamp() > at + timestamp_leeway { debug!(%deploy_hash, deploy_header = %self, %at, "deploy timestamp in the future"); - return Err(DeployConfigFailure::TimestampInFuture { + return Err(InvalidDeploy::TimestampInFuture { validation_timestamp: at, timestamp_leeway, got: self.timestamp(), diff --git a/types/src/transaction/deploy/error.rs b/types/src/transaction/deploy/error.rs index c00467cdd1..f846fee0b7 100644 --- a/types/src/transaction/deploy/error.rs +++ b/types/src/transaction/deploy/error.rs @@ -17,7 +17,7 @@ use crate::{crypto, TimeDiff, Timestamp, U512}; #[cfg_attr(feature = "std", derive(Serialize))] #[cfg_attr(feature = "datasize", derive(DataSize))] #[non_exhaustive] -pub enum DeployConfigFailure { +pub enum InvalidDeploy { /// Invalid chain name. InvalidChainName { /// The expected chain name. @@ -118,32 +118,38 @@ pub enum DeployConfigFailure { /// The chainspec limit for max_associated_keys. max_associated_keys: u32, }, + + /// Unable to calculate gas limit. + UnableToCalculateGasLimit, + + /// Unable to calculate gas cost. + UnableToCalculateGasCost, } -impl Display for DeployConfigFailure { +impl Display for InvalidDeploy { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { - DeployConfigFailure::InvalidChainName { expected, got } => { + InvalidDeploy::InvalidChainName { expected, got } => { write!( formatter, "invalid chain name: expected {}, got {}", expected, got ) } - DeployConfigFailure::DependenciesNoLongerSupported => { + InvalidDeploy::DependenciesNoLongerSupported => { write!(formatter, "dependencies no longer supported",) } - DeployConfigFailure::ExcessiveSize(error) => { + InvalidDeploy::ExcessiveSize(error) => { write!(formatter, "deploy size too large: {}", error) } - DeployConfigFailure::ExcessiveTimeToLive { max_ttl, got } => { + InvalidDeploy::ExcessiveTimeToLive { max_ttl, got } => { write!( formatter, "time-to-live of {} exceeds limit of {}", got, max_ttl ) } - DeployConfigFailure::TimestampInFuture { + InvalidDeploy::TimestampInFuture { validation_timestamp, timestamp_leeway, got, @@ -154,49 +160,49 @@ impl Display for DeployConfigFailure { got, validation_timestamp, timestamp_leeway ) } - DeployConfigFailure::InvalidBodyHash => { + InvalidDeploy::InvalidBodyHash => { write!( formatter, "the provided body hash does not match the actual hash of the body" ) } - DeployConfigFailure::InvalidDeployHash => { + InvalidDeploy::InvalidDeployHash => { write!( formatter, "the provided hash does not match the actual hash of the deploy" ) } - DeployConfigFailure::EmptyApprovals => { + InvalidDeploy::EmptyApprovals => { write!(formatter, "the deploy has no approvals") } - DeployConfigFailure::InvalidApproval { index, error } => { + InvalidDeploy::InvalidApproval { index, error } => { write!( formatter, "the approval at index {} is invalid: {}", index, error ) } - DeployConfigFailure::ExcessiveSessionArgsLength { max_length, got } => { + InvalidDeploy::ExcessiveSessionArgsLength { max_length, got } => { write!( formatter, "serialized session code runtime args of {} exceeds limit of {}", got, max_length ) } - DeployConfigFailure::ExcessivePaymentArgsLength { max_length, got } => { + InvalidDeploy::ExcessivePaymentArgsLength { max_length, got } => { write!( formatter, "serialized payment code runtime args of {} exceeds limit of {}", got, max_length ) } - DeployConfigFailure::MissingPaymentAmount => { + InvalidDeploy::MissingPaymentAmount => { write!(formatter, "missing payment 'amount' runtime argument") } - DeployConfigFailure::FailedToParsePaymentAmount => { + InvalidDeploy::FailedToParsePaymentAmount => { write!(formatter, "failed to parse payment 'amount' as U512") } - DeployConfigFailure::ExceededBlockGasLimit { + InvalidDeploy::ExceededBlockGasLimit { block_gas_limit, got, } => { @@ -206,20 +212,20 @@ impl Display for DeployConfigFailure { got, block_gas_limit ) } - DeployConfigFailure::MissingTransferAmount => { + InvalidDeploy::MissingTransferAmount => { write!(formatter, "missing transfer 'amount' runtime argument") } - DeployConfigFailure::FailedToParseTransferAmount => { + InvalidDeploy::FailedToParseTransferAmount => { write!(formatter, "failed to parse transfer 'amount' as U512") } - DeployConfigFailure::InsufficientTransferAmount { minimum, attempted } => { + InvalidDeploy::InsufficientTransferAmount { minimum, attempted } => { write!( formatter, "insufficient transfer amount; minimum: {} attempted: {}", minimum, attempted ) } - DeployConfigFailure::ExcessiveApprovals { + InvalidDeploy::ExcessiveApprovals { got, max_associated_keys, } => { @@ -229,38 +235,46 @@ impl Display for DeployConfigFailure { got, max_associated_keys ) } + InvalidDeploy::UnableToCalculateGasLimit => { + write!(formatter, "unable to calculate gas limit",) + } + InvalidDeploy::UnableToCalculateGasCost => { + write!(formatter, "unable to calculate gas cost",) + } } } } -impl From for DeployConfigFailure { +impl From for InvalidDeploy { fn from(error: ExcessiveSizeError) -> Self { - DeployConfigFailure::ExcessiveSize(error) + InvalidDeploy::ExcessiveSize(error) } } #[cfg(feature = "std")] -impl StdError for DeployConfigFailure { +impl StdError for InvalidDeploy { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { - DeployConfigFailure::InvalidApproval { error, .. } => Some(error), - DeployConfigFailure::InvalidChainName { .. } - | DeployConfigFailure::DependenciesNoLongerSupported { .. } - | DeployConfigFailure::ExcessiveSize(_) - | DeployConfigFailure::ExcessiveTimeToLive { .. } - | DeployConfigFailure::TimestampInFuture { .. } - | DeployConfigFailure::InvalidBodyHash - | DeployConfigFailure::InvalidDeployHash - | DeployConfigFailure::EmptyApprovals - | DeployConfigFailure::ExcessiveSessionArgsLength { .. } - | DeployConfigFailure::ExcessivePaymentArgsLength { .. } - | DeployConfigFailure::MissingPaymentAmount - | DeployConfigFailure::FailedToParsePaymentAmount - | DeployConfigFailure::ExceededBlockGasLimit { .. } - | DeployConfigFailure::MissingTransferAmount - | DeployConfigFailure::FailedToParseTransferAmount - | DeployConfigFailure::InsufficientTransferAmount { .. } - | DeployConfigFailure::ExcessiveApprovals { .. } => None, + InvalidDeploy::InvalidApproval { error, .. } => Some(error), + InvalidDeploy::InvalidChainName { .. } + | InvalidDeploy::DependenciesNoLongerSupported { .. } + | InvalidDeploy::ExcessiveSize(_) + | InvalidDeploy::ExcessiveTimeToLive { .. } + | InvalidDeploy::TimestampInFuture { .. } + | InvalidDeploy::InvalidBodyHash + | InvalidDeploy::InvalidDeployHash + | InvalidDeploy::EmptyApprovals + | InvalidDeploy::ExcessiveSessionArgsLength { .. } + | InvalidDeploy::ExcessivePaymentArgsLength { .. } + | InvalidDeploy::MissingPaymentAmount + | InvalidDeploy::FailedToParsePaymentAmount + | InvalidDeploy::ExceededBlockGasLimit { .. } + | InvalidDeploy::MissingTransferAmount + | InvalidDeploy::FailedToParseTransferAmount + | InvalidDeploy::InsufficientTransferAmount { .. } + | InvalidDeploy::ExcessiveApprovals { .. } + | InvalidDeploy::UnableToCalculateGasLimit + | InvalidDeploy::UnableToCalculateGasCost => None, } } } diff --git a/types/src/transaction/deploy/executable_deploy_item.rs b/types/src/transaction/deploy/executable_deploy_item.rs index e553a87c9d..42417734b8 100644 --- a/types/src/transaction/deploy/executable_deploy_item.rs +++ b/types/src/transaction/deploy/executable_deploy_item.rs @@ -16,14 +16,13 @@ use serde::{Deserialize, Serialize}; #[cfg(doc)] use super::Deploy; use crate::{ - account::AccountHash, addressable_entity::DEFAULT_ENTRY_POINT_NAME, bytesrepr::{self, Bytes, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, package::{EntityVersion, PackageHash}, runtime_args, serde_helpers, system::mint::ARG_AMOUNT, AddressableEntityHash, AddressableEntityIdentifier, Gas, Motes, PackageIdentifier, Phase, - PublicKey, RuntimeArgs, URef, U512, + RuntimeArgs, TransferTarget, URef, U512, }; #[cfg(any(feature = "testing", test))] use crate::{testing::TestRng, CLValue}; @@ -218,10 +217,10 @@ impl ExecutableDeployItem { /// Returns a new `ExecutableDeployItem` suitable for use as session code for a transfer. /// /// If `maybe_source` is None, the account's main purse is used as the source. - pub fn new_transfer>( + pub fn new_transfer, T: Into>( amount: A, maybe_source: Option, - target: TransferTarget, + target: T, maybe_transfer_id: Option, ) -> Self { let mut args = RuntimeArgs::new(); @@ -233,7 +232,7 @@ impl ExecutableDeployItem { .expect("should serialize source arg"); } - match target { + match target.into() { TransferTarget::PublicKey(public_key) => args .insert(TRANSFER_ARG_TARGET, public_key) .expect("should serialize public key target arg"), @@ -346,7 +345,7 @@ impl ExecutableDeployItem { } /// Returns the payment amount from args (if any) as Gas. - pub fn payment_amount(&self, conv_rate: u64) -> Option { + pub fn payment_amount(&self, conv_rate: u8) -> Option { let cl_value = self.args().get(ARG_AMOUNT)?; let motes = cl_value.clone().into_t::().ok()?; Gas::from_motes(Motes::new(motes), conv_rate) @@ -801,17 +800,6 @@ impl Distribution for Standard { } } -/// The various types which can be used as the `target` runtime argument of a native transfer. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] -pub enum TransferTarget { - /// A public key. - PublicKey(PublicKey), - /// An account hash. - AccountHash(AccountHash), - /// A URef. - URef(URef), -} - #[cfg(test)] mod tests { use super::*; diff --git a/types/src/transaction/error.rs b/types/src/transaction/error.rs new file mode 100644 index 0000000000..5d4e8cc32e --- /dev/null +++ b/types/src/transaction/error.rs @@ -0,0 +1,54 @@ +use crate::InvalidDeploy; +use core::fmt::{Display, Formatter}; +#[cfg(feature = "datasize")] +use datasize::DataSize; + +#[cfg(feature = "std")] +use serde::Serialize; +#[cfg(feature = "std")] +use std::error::Error as StdError; + +pub use crate::transaction::transaction_v1::InvalidTransactionV1; + +/// A representation of the way in which a transaction failed validation checks. +#[derive(Clone, Eq, PartialEq, Debug)] +#[cfg_attr(feature = "std", derive(Serialize))] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[non_exhaustive] +pub enum InvalidTransaction { + /// Legacy deploys. + Deploy(InvalidDeploy), + /// V1 transactions. + V1(InvalidTransactionV1), +} + +impl From for InvalidTransaction { + fn from(value: InvalidDeploy) -> Self { + Self::Deploy(value) + } +} + +impl From for InvalidTransaction { + fn from(value: InvalidTransactionV1) -> Self { + Self::V1(value) + } +} + +#[cfg(feature = "std")] +impl StdError for InvalidTransaction { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match self { + InvalidTransaction::Deploy(deploy) => deploy.source(), + InvalidTransaction::V1(v1) => v1.source(), + } + } +} + +impl Display for InvalidTransaction { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + InvalidTransaction::Deploy(inner) => Display::fmt(inner, f), + InvalidTransaction::V1(inner) => Display::fmt(inner, f), + } + } +} diff --git a/types/src/transaction/initiator_addr.rs b/types/src/transaction/initiator_addr.rs index 51a29be6a5..bd8aa69915 100644 --- a/types/src/transaction/initiator_addr.rs +++ b/types/src/transaction/initiator_addr.rs @@ -58,6 +58,18 @@ impl InitiatorAddr { } } +impl From for InitiatorAddr { + fn from(public_key: PublicKey) -> Self { + InitiatorAddr::PublicKey(public_key) + } +} + +impl From for InitiatorAddr { + fn from(account_hash: AccountHash) -> Self { + InitiatorAddr::AccountHash(account_hash) + } +} + impl Display for InitiatorAddr { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { diff --git a/types/src/transaction/pricing_mode.rs b/types/src/transaction/pricing_mode.rs index 1feed947fb..b50f13a52c 100644 --- a/types/src/transaction/pricing_mode.rs +++ b/types/src/transaction/pricing_mode.rs @@ -15,7 +15,7 @@ use super::Transaction; use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, - Digest, U512, + Digest, }; const CLASSIC_TAG: u8 = 0; @@ -38,7 +38,11 @@ pub enum PricingMode { /// User-specified payment amount. payment_amount: u64, /// User-specified gas_price tolerance (minimum 1). - gas_price: u64, + /// This is interpreted to mean "do not include this transaction in a block + /// if the current gas price is greater than this number" + gas_price_tolerance: u8, + /// Standard payment. + standard_payment: bool, }, /// The cost of the transaction is determined by the cost table, per the /// transaction kind. @@ -46,7 +50,7 @@ pub enum PricingMode { /// User-specified gas_price tolerance (minimum 1). /// This is interpreted to mean "do not include this transaction in a block /// if the current gas price is greater than this number" - gas_price_tolerance: u64, + gas_price_tolerance: u8, }, /// The payment for this transaction was previously reserved, as proven by /// the receipt hash (this is for future use, not currently implemented). @@ -54,7 +58,9 @@ pub enum PricingMode { /// Pre-paid receipt. receipt: Digest, /// Price paid in the past to reserve space in a future block. - paid_amount: U512, + paid_amount: u64, + /// The gas price at the time of reservation. + strike_price: u8, }, } @@ -65,7 +71,8 @@ impl PricingMode { match rng.gen_range(0..3) { 0 => PricingMode::Classic { payment_amount: rng.gen(), - gas_price: 1, + gas_price_tolerance: 1, + standard_payment: true, }, 1 => PricingMode::Fixed { gas_price_tolerance: rng.gen(), @@ -73,6 +80,7 @@ impl PricingMode { 2 => PricingMode::Reserved { receipt: rng.gen(), paid_amount: rng.gen(), + strike_price: rng.gen(), }, _ => unreachable!(), } @@ -84,21 +92,23 @@ impl Display for PricingMode { match self { PricingMode::Classic { payment_amount, - gas_price, + gas_price_tolerance: gas_price, + standard_payment, } => { write!( formatter, - "payment amount {}, gas price multiplier {}", - payment_amount, gas_price + "payment amount {}, gas price multiplier {} standard_payment {}", + payment_amount, gas_price, standard_payment ) } PricingMode::Reserved { receipt, paid_amount, + strike_price, } => write!( formatter, - "reserved: {} paid_amount: {}", - receipt, paid_amount + "reserved: {} paid_amount: {} strike_price: {}", + receipt, paid_amount, strike_price ), PricingMode::Fixed { gas_price_tolerance, @@ -112,19 +122,23 @@ impl ToBytes for PricingMode { match self { PricingMode::Classic { payment_amount, - gas_price, + gas_price_tolerance: gas_price, + standard_payment, } => { CLASSIC_TAG.write_bytes(writer)?; payment_amount.write_bytes(writer)?; - gas_price.write_bytes(writer) + gas_price.write_bytes(writer)?; + standard_payment.write_bytes(writer) } PricingMode::Reserved { receipt, paid_amount, + strike_price, } => { RESERVED_TAG.write_bytes(writer)?; receipt.write_bytes(writer)?; - paid_amount.write_bytes(writer) + paid_amount.write_bytes(writer)?; + strike_price.write_bytes(writer) } PricingMode::Fixed { gas_price_tolerance, @@ -146,12 +160,22 @@ impl ToBytes for PricingMode { + match self { PricingMode::Classic { payment_amount, - gas_price, - } => payment_amount.serialized_length() + gas_price.serialized_length(), + gas_price_tolerance: gas_price, + standard_payment, + } => { + payment_amount.serialized_length() + + gas_price.serialized_length() + + standard_payment.serialized_length() + } PricingMode::Reserved { receipt, paid_amount, - } => receipt.serialized_length() + paid_amount.serialized_length(), + strike_price, + } => { + receipt.serialized_length() + + paid_amount.serialized_length() + + strike_price.serialized_length() + } PricingMode::Fixed { gas_price_tolerance, } => gas_price_tolerance.serialized_length(), @@ -166,17 +190,19 @@ impl FromBytes for PricingMode { match tag { CLASSIC_TAG => { let (payment_amount, remainder) = u64::from_bytes(remainder)?; - let (gas_price, remainder) = u64::from_bytes(remainder)?; + let (gas_price, remainder) = u8::from_bytes(remainder)?; + let (standard_payment, remainder) = bool::from_bytes(remainder)?; Ok(( PricingMode::Classic { payment_amount, - gas_price, + gas_price_tolerance: gas_price, + standard_payment, }, remainder, )) } FIXED_TAG => { - let (gas_price_tolerance, remainder) = u64::from_bytes(remainder)?; + let (gas_price_tolerance, remainder) = u8::from_bytes(remainder)?; Ok(( PricingMode::Fixed { gas_price_tolerance, @@ -186,11 +212,13 @@ impl FromBytes for PricingMode { } RESERVED_TAG => { let (receipt, remainder) = Digest::from_bytes(remainder)?; - let (paid_amount, remainder) = U512::from_bytes(remainder)?; + let (paid_amount, remainder) = u64::from_bytes(remainder)?; + let (strike_price, remainder) = u8::from_bytes(remainder)?; Ok(( PricingMode::Reserved { receipt, paid_amount, + strike_price, }, remainder, )) diff --git a/types/src/transaction/transaction_entry_point.rs b/types/src/transaction/transaction_entry_point.rs index c7a64e429d..c53f0056d2 100644 --- a/types/src/transaction/transaction_entry_point.rs +++ b/types/src/transaction/transaction_entry_point.rs @@ -141,7 +141,8 @@ pub enum TransactionEntryPoint { #[cfg_attr( feature = "json-schema", schemars( - description = "The `activate_bid` native entry point, used to used to reactivate an inactive bid." + description = "The `activate_bid` native entry point, used to used to reactivate an \ + inactive bid." ) )] ActivateBid, @@ -163,6 +164,20 @@ impl TransactionEntryPoint { _ => unreachable!(), } } + + /// Does this entry point kind require holds epoch? + pub fn requires_holds_epoch(&self) -> bool { + match self { + TransactionEntryPoint::AddBid + | TransactionEntryPoint::Delegate + | TransactionEntryPoint::Custom(_) + | TransactionEntryPoint::Transfer => true, + TransactionEntryPoint::WithdrawBid + | TransactionEntryPoint::Undelegate + | TransactionEntryPoint::Redelegate + | TransactionEntryPoint::ActivateBid => false, + } + } } impl Display for TransactionEntryPoint { diff --git a/types/src/transaction/transaction_hash.rs b/types/src/transaction/transaction_hash.rs index 8ae7631122..76a674a961 100644 --- a/types/src/transaction/transaction_hash.rs +++ b/types/src/transaction/transaction_hash.rs @@ -3,25 +3,23 @@ use core::fmt::{self, Display, Formatter}; #[cfg(feature = "datasize")] use datasize::DataSize; +#[cfg(any(feature = "testing", test))] +use rand::Rng; #[cfg(feature = "json-schema")] use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[cfg(doc)] -use super::TransactionV1; use super::{DeployHash, TransactionV1Hash}; +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; use crate::{ bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, Digest, }; -#[cfg(any(feature = "testing", test))] -use crate::testing::TestRng; -#[cfg(any(feature = "testing", test))] -use rand::Rng; - const DEPLOY_TAG: u8 = 0; const V1_TAG: u8 = 1; +const TAG_LENGTH: u8 = 1; /// A versioned wrapper for a transaction hash or deploy hash. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] @@ -37,6 +35,8 @@ pub enum TransactionHash { } impl TransactionHash { + /// The number of bytes in a `DeployHash` digest. + pub const LENGTH: usize = TAG_LENGTH as usize + Digest::LENGTH; /// Digest representation of hash. pub fn digest(&self) -> Digest { match self { @@ -54,6 +54,12 @@ impl TransactionHash { _ => panic!(), } } + + /// Returns a new `TransactionHash` directly initialized with the provided bytes; no hashing + /// is done. + pub const fn from_raw(raw_digest: [u8; TransactionV1Hash::LENGTH]) -> Self { + TransactionHash::V1(TransactionV1Hash::from_raw(raw_digest)) + } } impl From for TransactionHash { @@ -80,6 +86,12 @@ impl From<&TransactionV1Hash> for TransactionHash { } } +impl Default for TransactionHash { + fn default() -> Self { + TransactionHash::V1(TransactionV1Hash::default()) + } +} + impl Display for TransactionHash { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { @@ -99,19 +111,6 @@ impl AsRef<[u8]> for TransactionHash { } impl ToBytes for TransactionHash { - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - match self { - TransactionHash::Deploy(hash) => { - DEPLOY_TAG.write_bytes(writer)?; - hash.write_bytes(writer) - } - TransactionHash::V1(hash) => { - V1_TAG.write_bytes(writer)?; - hash.write_bytes(writer) - } - } - } - fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; @@ -125,6 +124,19 @@ impl ToBytes for TransactionHash { TransactionHash::V1(hash) => hash.serialized_length(), } } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + match self { + TransactionHash::Deploy(hash) => { + DEPLOY_TAG.write_bytes(writer)?; + hash.write_bytes(writer) + } + TransactionHash::V1(hash) => { + V1_TAG.write_bytes(writer)?; + hash.write_bytes(writer) + } + } + } } impl FromBytes for TransactionHash { diff --git a/types/src/transaction/transaction_header.rs b/types/src/transaction/transaction_header.rs index d1a864bb84..68b5d7f3bd 100644 --- a/types/src/transaction/transaction_header.rs +++ b/types/src/transaction/transaction_header.rs @@ -9,7 +9,10 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use super::{DeployHeader, TransactionV1Header}; -use crate::bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}; +use crate::{ + bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}, + InitiatorAddr, +}; const DEPLOY_TAG: u8 = 0; const V1_TAG: u8 = 1; @@ -31,15 +34,25 @@ pub enum TransactionHeader { V1(TransactionV1Header), } +impl TransactionHeader { + /// Return the initiator addr of this transaction. + pub fn initiator_addr(&self) -> InitiatorAddr { + match self { + TransactionHeader::Deploy(header) => header.account().clone().into(), + TransactionHeader::V1(header) => header.initiator_addr().clone(), + } + } +} + impl From for TransactionHeader { - fn from(hash: DeployHeader) -> Self { - Self::Deploy(hash) + fn from(header: DeployHeader) -> Self { + Self::Deploy(header) } } impl From for TransactionHeader { - fn from(hash: TransactionV1Header) -> Self { - Self::V1(hash) + fn from(header: TransactionV1Header) -> Self { + Self::V1(header) } } diff --git a/types/src/transaction/transaction_invocation_target.rs b/types/src/transaction/transaction_invocation_target.rs index 89de3655a5..227b3dd1a7 100644 --- a/types/src/transaction/transaction_invocation_target.rs +++ b/types/src/transaction/transaction_invocation_target.rs @@ -45,11 +45,11 @@ pub enum TransactionInvocationTarget { description = "Hex-encoded entity address identifying the invocable entity." ) )] - InvocableEntity(HashAddr), // currently needs to be of contract tag variant + ByHash(HashAddr), // currently needs to be of contract tag variant /// The alias identifying the invocable entity. - InvocableEntityAlias(String), + ByName(String), /// The address and optional version identifying the package. - Package { + ByPackageHash { /// The package address. #[serde(with = "serde_helpers::raw_32_byte_array")] #[cfg_attr( @@ -63,9 +63,9 @@ pub enum TransactionInvocationTarget { version: Option, }, /// The alias and optional version identifying the package. - PackageAlias { + ByPackageName { /// The package alias. - alias: String, + name: String, /// The package version. /// /// If `None`, the latest enabled version is implied. @@ -75,56 +75,62 @@ pub enum TransactionInvocationTarget { impl TransactionInvocationTarget { /// Returns a new `TransactionInvocationTarget::InvocableEntity`. - pub fn new_invocable_entity(addr: HashAddr) -> Self { - TransactionInvocationTarget::InvocableEntity(addr) + pub fn new_invocable_entity(hash: AddressableEntityHash) -> Self { + TransactionInvocationTarget::ByHash(hash.value()) } /// Returns a new `TransactionInvocationTarget::InvocableEntityAlias`. pub fn new_invocable_entity_alias(alias: String) -> Self { - TransactionInvocationTarget::InvocableEntityAlias(alias) + TransactionInvocationTarget::ByName(alias) } /// Returns a new `TransactionInvocationTarget::Package`. - pub fn new_package(addr: PackageAddr, version: Option) -> Self { - TransactionInvocationTarget::Package { addr, version } + pub fn new_package(hash: PackageHash, version: Option) -> Self { + TransactionInvocationTarget::ByPackageHash { + addr: hash.value(), + version, + } } /// Returns a new `TransactionInvocationTarget::PackageAlias`. pub fn new_package_alias(alias: String, version: Option) -> Self { - TransactionInvocationTarget::PackageAlias { alias, version } + TransactionInvocationTarget::ByPackageName { + name: alias, + version, + } } /// Returns the identifier of the addressable entity, if present. pub fn addressable_entity_identifier(&self) -> Option { match self { - TransactionInvocationTarget::InvocableEntity(addr) => Some( - AddressableEntityIdentifier::Hash(AddressableEntityHash::new(*addr)), - ), - TransactionInvocationTarget::InvocableEntityAlias(alias) => { + TransactionInvocationTarget::ByHash(addr) => Some(AddressableEntityIdentifier::Hash( + AddressableEntityHash::new(*addr), + )), + TransactionInvocationTarget::ByName(alias) => { Some(AddressableEntityIdentifier::Name(alias.clone())) } - TransactionInvocationTarget::Package { .. } - | TransactionInvocationTarget::PackageAlias { .. } => None, + TransactionInvocationTarget::ByPackageHash { .. } + | TransactionInvocationTarget::ByPackageName { .. } => None, } } /// Returns the identifier of the contract package, if present. pub fn package_identifier(&self) -> Option { match self { - TransactionInvocationTarget::InvocableEntity(_) - | TransactionInvocationTarget::InvocableEntityAlias(_) => None, - TransactionInvocationTarget::Package { addr, version } => { + TransactionInvocationTarget::ByHash(_) | TransactionInvocationTarget::ByName(_) => None, + TransactionInvocationTarget::ByPackageHash { addr, version } => { Some(PackageIdentifier::Hash { package_hash: PackageHash::new(*addr), version: *version, }) } - TransactionInvocationTarget::PackageAlias { alias, version } => { - Some(PackageIdentifier::Name { - name: alias.clone(), - version: *version, - }) - } + TransactionInvocationTarget::ByPackageName { + name: alias, + version, + } => Some(PackageIdentifier::Name { + name: alias.clone(), + version: *version, + }), } } @@ -132,16 +138,16 @@ impl TransactionInvocationTarget { #[cfg(any(feature = "testing", test))] pub fn random(rng: &mut TestRng) -> Self { match rng.gen_range(0..4) { - INVOCABLE_ENTITY_TAG => TransactionInvocationTarget::InvocableEntity(rng.gen()), + INVOCABLE_ENTITY_TAG => TransactionInvocationTarget::ByHash(rng.gen()), INVOCABLE_ENTITY_ALIAS_TAG => { - TransactionInvocationTarget::InvocableEntityAlias(rng.random_string(1..21)) + TransactionInvocationTarget::ByName(rng.random_string(1..21)) } - PACKAGE_TAG => TransactionInvocationTarget::Package { + PACKAGE_TAG => TransactionInvocationTarget::ByPackageHash { addr: rng.gen(), version: rng.gen::().then(|| rng.gen::()), }, - PACKAGE_ALIAS_TAG => TransactionInvocationTarget::PackageAlias { - alias: rng.random_string(1..21), + PACKAGE_ALIAS_TAG => TransactionInvocationTarget::ByPackageName { + name: rng.random_string(1..21), version: rng.gen::().then(|| rng.gen::()), }, _ => unreachable!(), @@ -152,32 +158,32 @@ impl TransactionInvocationTarget { impl Display for TransactionInvocationTarget { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { - TransactionInvocationTarget::InvocableEntity(addr) => { + TransactionInvocationTarget::ByHash(addr) => { write!(formatter, "invocable-entity({:10})", HexFmt(addr)) } - TransactionInvocationTarget::InvocableEntityAlias(alias) => { + TransactionInvocationTarget::ByName(alias) => { write!(formatter, "invocable-entity({})", alias) } - TransactionInvocationTarget::Package { + TransactionInvocationTarget::ByPackageHash { addr, version: Some(ver), } => { write!(formatter, "package({:10}, version {})", HexFmt(addr), ver) } - TransactionInvocationTarget::Package { + TransactionInvocationTarget::ByPackageHash { addr, version: None, } => { write!(formatter, "package({:10}, latest)", HexFmt(addr)) } - TransactionInvocationTarget::PackageAlias { - alias, + TransactionInvocationTarget::ByPackageName { + name: alias, version: Some(ver), } => { write!(formatter, "package({}, version {})", alias, ver) } - TransactionInvocationTarget::PackageAlias { - alias, + TransactionInvocationTarget::ByPackageName { + name: alias, version: None, } => { write!(formatter, "package({}, latest)", alias) @@ -189,20 +195,23 @@ impl Display for TransactionInvocationTarget { impl Debug for TransactionInvocationTarget { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { - TransactionInvocationTarget::InvocableEntity(addr) => formatter + TransactionInvocationTarget::ByHash(addr) => formatter .debug_tuple("InvocableEntity") .field(&HexFmt(addr)) .finish(), - TransactionInvocationTarget::InvocableEntityAlias(alias) => formatter + TransactionInvocationTarget::ByName(alias) => formatter .debug_tuple("InvocableEntityAlias") .field(alias) .finish(), - TransactionInvocationTarget::Package { addr, version } => formatter + TransactionInvocationTarget::ByPackageHash { addr, version } => formatter .debug_struct("Package") .field("addr", &HexFmt(addr)) .field("version", version) .finish(), - TransactionInvocationTarget::PackageAlias { alias, version } => formatter + TransactionInvocationTarget::ByPackageName { + name: alias, + version, + } => formatter .debug_struct("PackageAlias") .field("alias", alias) .field("version", version) @@ -214,20 +223,23 @@ impl Debug for TransactionInvocationTarget { impl ToBytes for TransactionInvocationTarget { fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { match self { - TransactionInvocationTarget::InvocableEntity(addr) => { + TransactionInvocationTarget::ByHash(addr) => { INVOCABLE_ENTITY_TAG.write_bytes(writer)?; addr.write_bytes(writer) } - TransactionInvocationTarget::InvocableEntityAlias(alias) => { + TransactionInvocationTarget::ByName(alias) => { INVOCABLE_ENTITY_ALIAS_TAG.write_bytes(writer)?; alias.write_bytes(writer) } - TransactionInvocationTarget::Package { addr, version } => { + TransactionInvocationTarget::ByPackageHash { addr, version } => { PACKAGE_TAG.write_bytes(writer)?; addr.write_bytes(writer)?; version.write_bytes(writer) } - TransactionInvocationTarget::PackageAlias { alias, version } => { + TransactionInvocationTarget::ByPackageName { + name: alias, + version, + } => { PACKAGE_ALIAS_TAG.write_bytes(writer)?; alias.write_bytes(writer)?; version.write_bytes(writer) @@ -244,16 +256,15 @@ impl ToBytes for TransactionInvocationTarget { fn serialized_length(&self) -> usize { U8_SERIALIZED_LENGTH + match self { - TransactionInvocationTarget::InvocableEntity(addr) => addr.serialized_length(), - TransactionInvocationTarget::InvocableEntityAlias(alias) => { - alias.serialized_length() - } - TransactionInvocationTarget::Package { addr, version } => { + TransactionInvocationTarget::ByHash(addr) => addr.serialized_length(), + TransactionInvocationTarget::ByName(alias) => alias.serialized_length(), + TransactionInvocationTarget::ByPackageHash { addr, version } => { addr.serialized_length() + version.serialized_length() } - TransactionInvocationTarget::PackageAlias { alias, version } => { - alias.serialized_length() + version.serialized_length() - } + TransactionInvocationTarget::ByPackageName { + name: alias, + version, + } => alias.serialized_length() + version.serialized_length(), } } } @@ -264,24 +275,27 @@ impl FromBytes for TransactionInvocationTarget { match tag { INVOCABLE_ENTITY_TAG => { let (addr, remainder) = HashAddr::from_bytes(remainder)?; - let target = TransactionInvocationTarget::InvocableEntity(addr); + let target = TransactionInvocationTarget::ByHash(addr); Ok((target, remainder)) } INVOCABLE_ENTITY_ALIAS_TAG => { let (alias, remainder) = String::from_bytes(remainder)?; - let target = TransactionInvocationTarget::InvocableEntityAlias(alias); + let target = TransactionInvocationTarget::ByName(alias); Ok((target, remainder)) } PACKAGE_TAG => { let (addr, remainder) = PackageAddr::from_bytes(remainder)?; let (version, remainder) = Option::::from_bytes(remainder)?; - let target = TransactionInvocationTarget::Package { addr, version }; + let target = TransactionInvocationTarget::ByPackageHash { addr, version }; Ok((target, remainder)) } PACKAGE_ALIAS_TAG => { let (alias, remainder) = String::from_bytes(remainder)?; let (version, remainder) = Option::::from_bytes(remainder)?; - let target = TransactionInvocationTarget::PackageAlias { alias, version }; + let target = TransactionInvocationTarget::ByPackageName { + name: alias, + version, + }; Ok((target, remainder)) } _ => Err(bytesrepr::Error::Formatting), diff --git a/types/src/transaction/transaction_v1.rs b/types/src/transaction/transaction_v1.rs index cd9c3fcc81..a72ddc88b8 100644 --- a/types/src/transaction/transaction_v1.rs +++ b/types/src/transaction/transaction_v1.rs @@ -25,28 +25,26 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use tracing::debug; -#[cfg(any(feature = "std", test))] -use super::InitiatorAddrAndSecretKey; use super::{ - Approval, ApprovalsHash, InitiatorAddr, PricingMode, TransactionEntryPoint, + Approval, ApprovalsHash, Categorized, InitiatorAddr, PricingMode, TransactionEntryPoint, TransactionScheduling, TransactionTarget, }; -#[cfg(any(all(feature = "std", feature = "testing"), test))] -use crate::testing::TestRng; #[cfg(any(feature = "std", test))] -use crate::{Gas, Motes, TransactionConfig, U512}; - -#[cfg(any(feature = "std", test))] -use crate::SystemConfig; - +use super::{GasLimited, InitiatorAddrAndSecretKey}; use crate::{ bytesrepr::{self, FromBytes, ToBytes}, - crypto, Digest, DisplayIter, RuntimeArgs, SecretKey, TimeDiff, Timestamp, + crypto, Digest, DisplayIter, RuntimeArgs, SecretKey, TimeDiff, Timestamp, TransactionRuntime, TransactionSessionKind, }; +#[cfg(any(feature = "std", test))] +use crate::{chainspec::Chainspec, chainspec::PricingHandling}; + +#[cfg(any(feature = "std", test))] +use crate::{Gas, Motes, TransactionConfig, U512}; pub use errors_v1::{ DecodeFromJsonErrorV1 as TransactionV1DecodeFromJsonError, ErrorV1 as TransactionV1Error, - ExcessiveSizeErrorV1 as TransactionV1ExcessiveSizeError, TransactionV1ConfigFailure, + ExcessiveSizeErrorV1 as TransactionV1ExcessiveSizeError, + InvalidTransaction as InvalidTransactionV1, }; pub use transaction_v1_body::TransactionV1Body; #[cfg(any(feature = "std", test))] @@ -55,6 +53,9 @@ pub use transaction_v1_category::TransactionCategory; pub use transaction_v1_hash::TransactionV1Hash; pub use transaction_v1_header::TransactionV1Header; +#[cfg(any(all(feature = "std", feature = "testing"), test))] +use crate::testing::TestRng; + /// A unit of work sent by a client to the network, which when executed can cause global state to /// be altered. /// @@ -85,7 +86,7 @@ pub struct TransactionV1 { data_size(skip) )] #[cfg(any(feature = "once_cell", test))] - is_verified: OnceCell>, + is_verified: OnceCell>, } impl TransactionV1 { @@ -181,6 +182,11 @@ impl TransactionV1 { self.body.args() } + /// Consumes `self`, returning the runtime args of the transaction. + pub fn take_args(self) -> RuntimeArgs { + self.body.take_args() + } + /// Returns the target of the transaction. pub fn target(&self) -> &TransactionTarget { self.body.target() @@ -201,91 +207,61 @@ impl TransactionV1 { &self.body } - /// This transaction is a native mint interaction. + /// Returns true if this transaction is a native mint interaction. pub fn is_native_mint(&self) -> bool { self.body().is_native_mint() } - /// This transaction is a native auction interaction. + /// Returns true if this transaction is a native auction interaction. pub fn is_native_auction(&self) -> bool { self.body().is_native_auction() } - /// This transaction is a smart contract installer or upgrader. + /// Returns true if this transaction is a smart contract installer or upgrader. pub fn is_install_or_upgrade(&self) -> bool { self.body().is_install_or_upgrade() } - /// This transaction goes into the misc / standard category. + /// Returns true if this transaction goes into the misc / standard category. pub fn is_standard(&self) -> bool { self.body().is_standard() } - /// Returns the gas limit for this transaction. - #[cfg(any(feature = "std", test))] - pub fn gas_limit(&self, costs: &SystemConfig, gas_price: Option) -> Option { - match self.header().pricing_mode() { - PricingMode::Classic { - payment_amount, - gas_price: user_specified_price, - } => { - let actual_price = match gas_price { - Some(system_specified_price) => { - // take the higher of the two possible prices - (*user_specified_price).max(system_specified_price) - } - None => *user_specified_price, - }; - let motes = Motes::new(U512::from(*payment_amount)); - Gas::from_motes(motes, actual_price) - } - PricingMode::Fixed { .. } => { - // if gas price is not provided, assume price == 1 - let gas_price = gas_price.unwrap_or(1); - let cost = { - if self.is_native_mint() { - // Because we currently only support one native mint interaction, - // native transfer, we can short circuit to return that value. - // However if other direct mint interactions are supported - // in the future (such as the upcoming burn feature), - // this logic will need to be expanded to self.mint_costs().field? - // for the value for each verb...see how auction is set up below. - costs.mint_costs().transfer - } else if self.is_native_auction() { - match self.body().entry_point() { - TransactionEntryPoint::Custom(_) | TransactionEntryPoint::Transfer => { - unreachable!("this must be programmer error"); - } - TransactionEntryPoint::AddBid | TransactionEntryPoint::ActivateBid => { - costs.auction_costs().add_bid - } - TransactionEntryPoint::WithdrawBid => { - costs.auction_costs().withdraw_bid - } - TransactionEntryPoint::Delegate => costs.auction_costs().delegate, - TransactionEntryPoint::Undelegate => costs.auction_costs().undelegate, - TransactionEntryPoint::Redelegate => costs.auction_costs().redelegate, - } - } else if self.is_install_or_upgrade() { - costs.install_upgrade_limit() - } else { - costs.standard_transaction_limit() - } - }; - Gas::from_motes(Motes::new(U512::from(cost)), gas_price) - } - PricingMode::Reserved { paid_amount, .. } => { - // prepaid, if receipt is legit (future use, not currently implemented) - Gas::from_motes(Motes::new(U512::from(paid_amount)), 1) + /// Does this transaction have wasm targeting the v1 vm. + pub fn is_v1_wasm(&self) -> bool { + match self.target() { + TransactionTarget::Native => false, + TransactionTarget::Stored { runtime, .. } + | TransactionTarget::Session { runtime, .. } => { + matches!(runtime, TransactionRuntime::VmCasperV1) + && (self.is_standard() || self.is_install_or_upgrade()) } } } + /// Should this transaction start in the initiating accounts context? + pub fn is_account_session(&self) -> bool { + let target_is_stored_contract = matches!(self.target(), TransactionTarget::Stored { .. }); + !target_is_stored_contract + } + /// Returns the approvals for this transaction. pub fn approvals(&self) -> &BTreeSet { &self.approvals } + /// Consumes `self`, returning a tuple of its constituent parts. + pub fn destructure( + self, + ) -> ( + TransactionV1Hash, + TransactionV1Header, + TransactionV1Body, + BTreeSet, + ) { + (self.hash, self.header, self.body, self.approvals) + } + /// 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); @@ -316,7 +292,7 @@ impl TransactionV1 { /// Returns `Ok` if and only if this transaction's body hashes to the value of `body_hash()`, /// and if this transaction's header hashes to the value claimed as the transaction hash. - pub fn has_valid_hash(&self) -> Result<(), TransactionV1ConfigFailure> { + pub fn has_valid_hash(&self) -> Result<(), InvalidTransactionV1> { let body_hash = Digest::hash( self.body .to_bytes() @@ -324,7 +300,7 @@ impl TransactionV1 { ); if body_hash != *self.header.body_hash() { debug!(?self, ?body_hash, "invalid transaction body hash"); - return Err(TransactionV1ConfigFailure::InvalidBodyHash); + return Err(InvalidTransactionV1::InvalidBodyHash); } let hash = TransactionV1Hash::new(Digest::hash( @@ -334,7 +310,7 @@ impl TransactionV1 { )); if hash != self.hash { debug!(?self, ?hash, "invalid transaction hash"); - return Err(TransactionV1ConfigFailure::InvalidTransactionHash); + return Err(InvalidTransactionV1::InvalidTransactionHash); } Ok(()) } @@ -343,7 +319,7 @@ impl TransactionV1 { /// * the transaction hash is correct (see [`TransactionV1::has_valid_hash`] for details) /// * approvals are non empty, and /// * all approvals are valid signatures of the signed hash - pub fn verify(&self) -> Result<(), TransactionV1ConfigFailure> { + pub fn verify(&self) -> Result<(), InvalidTransactionV1> { #[cfg(any(feature = "once_cell", test))] return self.is_verified.get_or_init(|| self.do_verify()).clone(); @@ -351,10 +327,10 @@ impl TransactionV1 { self.do_verify() } - fn do_verify(&self) -> Result<(), TransactionV1ConfigFailure> { + fn do_verify(&self) -> Result<(), InvalidTransactionV1> { if self.approvals.is_empty() { debug!(?self, "transaction has no approvals"); - return Err(TransactionV1ConfigFailure::EmptyApprovals); + return Err(InvalidTransactionV1::EmptyApprovals); } self.has_valid_hash()?; @@ -365,7 +341,7 @@ impl TransactionV1 { ?self, "failed to verify transaction approval {}: {}", index, error ); - return Err(TransactionV1ConfigFailure::InvalidApproval { index, error }); + return Err(InvalidTransactionV1::InvalidApproval { index, error }); } } @@ -378,15 +354,15 @@ impl TransactionV1 { #[cfg(any(feature = "std", test))] pub fn is_config_compliant( &self, - chain_name: &str, - cost_table: &SystemConfig, - transaction_config: &TransactionConfig, - max_associated_keys: u32, + chainspec: &Chainspec, timestamp_leeway: TimeDiff, at: Timestamp, - ) -> Result<(), TransactionV1ConfigFailure> { + ) -> Result<(), InvalidTransactionV1> { + let transaction_config = chainspec.transaction_config; self.is_valid_size(transaction_config.max_transaction_size)?; + let chain_name = chainspec.network_config.name.clone(); + let header = self.header(); if header.chain_name() != chain_name { debug!( @@ -395,13 +371,46 @@ impl TransactionV1 { chain_name = %header.chain_name(), "invalid chain identifier" ); - return Err(TransactionV1ConfigFailure::InvalidChainName { - expected: chain_name.to_string(), + return Err(InvalidTransactionV1::InvalidChainName { + expected: chain_name, got: header.chain_name().to_string(), }); } - header.is_valid(transaction_config, timestamp_leeway, at, &self.hash)?; + let price_handling = chainspec.core_config.pricing_handling; + let price_mode = header.pricing_mode(); + + match price_mode { + PricingMode::Classic { .. } => { + if let PricingHandling::Classic = price_handling { + } else { + return Err(InvalidTransactionV1::InvalidPricingMode { + price_mode: price_mode.clone(), + }); + } + } + PricingMode::Fixed { .. } => { + if let PricingHandling::Fixed = price_handling { + } else { + return Err(InvalidTransactionV1::InvalidPricingMode { + price_mode: price_mode.clone(), + }); + } + } + PricingMode::Reserved { .. } => { + if !chainspec.core_config.allow_reservations { + // Currently Reserved isn't implemented and we should + // not be accepting transactions with this mode. + return Err(InvalidTransactionV1::InvalidPricingMode { + price_mode: price_mode.clone(), + }); + } + } + } + + header.is_valid(&transaction_config, timestamp_leeway, at, &self.hash)?; + + let max_associated_keys = chainspec.core_config.max_associated_keys; if self.approvals.len() > max_associated_keys as usize { debug!( @@ -410,28 +419,27 @@ impl TransactionV1 { max_associated_keys = %max_associated_keys, "number of transaction approvals exceeds the limit" ); - return Err(TransactionV1ConfigFailure::ExcessiveApprovals { + return Err(InvalidTransactionV1::ExcessiveApprovals { got: self.approvals.len() as u32, max_associated_keys, }); } - if let Some(gas_limit) = self.gas_limit(cost_table, None) { - let block_gas_limit = Gas::new(U512::from(transaction_config.block_gas_limit)); - if gas_limit > block_gas_limit { - debug!( - amount = %gas_limit, - %block_gas_limit, - "transaction gas limit exceeds block gas limit" - ); - return Err(TransactionV1ConfigFailure::ExceedsBlockGasLimit { - block_gas_limit: transaction_config.block_gas_limit, - got: Box::new(gas_limit.value()), - }); - } + let gas_limit = self.gas_limit(chainspec)?; + let block_gas_limit = Gas::new(U512::from(transaction_config.block_gas_limit)); + if gas_limit > block_gas_limit { + debug!( + amount = %gas_limit, + %block_gas_limit, + "transaction gas limit exceeds block gas limit" + ); + return Err(InvalidTransactionV1::ExceedsBlockGasLimit { + block_gas_limit: transaction_config.block_gas_limit, + got: Box::new(gas_limit.value()), + }); } - self.body.is_valid(transaction_config) + self.body.is_valid(&transaction_config) } // This method is not intended to be used by third party crates. @@ -592,6 +600,101 @@ impl TransactionV1 { } } +impl Categorized for TransactionV1 { + fn category(&self) -> TransactionCategory { + if self.is_native_mint() { + TransactionCategory::Mint + } else if self.is_native_auction() { + TransactionCategory::Auction + } else if self.is_install_or_upgrade() { + TransactionCategory::InstallUpgrade + } else { + TransactionCategory::Standard + } + } +} + +#[cfg(any(feature = "std", test))] +impl GasLimited for TransactionV1 { + type Error = InvalidTransactionV1; + + fn gas_cost(&self, chainspec: &Chainspec, gas_price: u8) -> Result { + let gas_limit = self.gas_limit(chainspec)?; + let motes = match self.header().pricing_mode() { + PricingMode::Classic { .. } | PricingMode::Fixed { .. } => { + Motes::from_gas(gas_limit, gas_price) + .ok_or(InvalidTransactionV1::UnableToCalculateGasCost)? + } + PricingMode::Reserved { .. } => { + Motes::zero() // prepaid + } + }; + Ok(motes) + } + + fn gas_limit(&self, chainspec: &Chainspec) -> Result { + let costs = chainspec.system_costs_config; + let gas = match self.header().pricing_mode() { + PricingMode::Classic { payment_amount, .. } => Gas::new(*payment_amount), + PricingMode::Fixed { .. } => { + let computation_limit = { + if self.is_native_mint() { + // Because we currently only support one native mint interaction, + // native transfer, we can short circuit to return that value. + // However if other direct mint interactions are supported + // in the future (such as the upcoming burn feature), + // this logic will need to be expanded to self.mint_costs().field? + // for the value for each verb...see how auction is set up below. + costs.mint_costs().transfer as u64 + } else if self.is_native_auction() { + let entry_point = self.body().entry_point(); + let amount = match entry_point { + TransactionEntryPoint::Custom(_) | TransactionEntryPoint::Transfer => { + return Err(InvalidTransactionV1::EntryPointCannotBeCustom { + entry_point: entry_point.clone(), + }) + } + TransactionEntryPoint::AddBid | TransactionEntryPoint::ActivateBid => { + costs.auction_costs().add_bid + } + TransactionEntryPoint::WithdrawBid => { + costs.auction_costs().withdraw_bid + } + TransactionEntryPoint::Delegate => costs.auction_costs().delegate, + TransactionEntryPoint::Undelegate => costs.auction_costs().undelegate, + TransactionEntryPoint::Redelegate => costs.auction_costs().redelegate, + }; + amount as u64 + } else if self.is_install_or_upgrade() { + costs.install_upgrade_limit() + } else { + costs.standard_transaction_limit() + } + }; + Gas::new(U512::from(computation_limit)) + } + PricingMode::Reserved { + paid_amount, + strike_price, + .. + } => { + // prepaid, if receipt is legit (future use) + Gas::from_price(U512::from(*paid_amount), *strike_price).ok_or( + InvalidTransactionV1::GasPriceConversion { + amount: *paid_amount, + gas_price: *strike_price, + }, + )? + } + }; + Ok(gas) + } + + fn gas_price_tolerance(&self) -> Result { + Ok(self.header.gas_price_tolerance()) + } +} + impl hash::Hash for TransactionV1 { fn hash(&self, state: &mut H) { // Destructure to make sure we don't accidentally omit fields. @@ -757,7 +860,7 @@ mod tests { fn check_is_not_valid( invalid_transaction: TransactionV1, - expected_error: TransactionV1ConfigFailure, + expected_error: InvalidTransactionV1, ) { assert!( invalid_transaction.is_verified.get().is_none(), @@ -769,11 +872,11 @@ mod tests { // this makes the test too fragile. Otherwise expect the actual error should exactly match // the expected error. match expected_error { - TransactionV1ConfigFailure::InvalidApproval { + InvalidTransactionV1::InvalidApproval { index: expected_index, .. } => match actual_error { - TransactionV1ConfigFailure::InvalidApproval { + InvalidTransactionV1::InvalidApproval { index: actual_index, .. } => { @@ -800,10 +903,7 @@ mod tests { let mut transaction = TransactionV1::random(rng); transaction.invalidate(); - check_is_not_valid( - transaction, - TransactionV1ConfigFailure::InvalidTransactionHash, - ); + check_is_not_valid(transaction, InvalidTransactionV1::InvalidTransactionHash); } #[test] @@ -814,7 +914,7 @@ mod tests { .build() .unwrap(); assert!(transaction.approvals.is_empty()); - check_is_not_valid(transaction, TransactionV1ConfigFailure::EmptyApprovals) + check_is_not_valid(transaction, InvalidTransactionV1::EmptyApprovals) } #[test] @@ -840,7 +940,7 @@ mod tests { .unwrap(); check_is_not_valid( transaction, - TransactionV1ConfigFailure::InvalidApproval { + InvalidTransactionV1::InvalidApproval { index: expected_index, error: crypto::Error::SignatureError, // This field is ignored in the check. }, @@ -855,18 +955,14 @@ mod tests { .with_chain_name(chain_name) .build() .unwrap(); - let cost_table = SystemConfig::default(); - let transaction_config = TransactionConfig::default(); let current_timestamp = transaction.timestamp(); + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret + }; transaction - .is_config_compliant( - chain_name, - &cost_table, - &transaction_config, - MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp, - ) + .is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp) .expect("should be acceptable"); } @@ -875,29 +971,24 @@ mod tests { let rng = &mut TestRng::new(); let expected_chain_name = "net-1"; let wrong_chain_name = "net-2"; - let cost_table = SystemConfig::default(); - let transaction_config = TransactionConfig::default(); - let transaction = TransactionV1Builder::new_random(rng) .with_chain_name(wrong_chain_name) .build() .unwrap(); - let expected_error = TransactionV1ConfigFailure::InvalidChainName { + let expected_error = InvalidTransactionV1::InvalidChainName { expected: expected_chain_name.to_string(), got: wrong_chain_name.to_string(), }; let current_timestamp = transaction.timestamp(); + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = expected_chain_name.to_string(); + ret + }; assert_eq!( - transaction.is_config_compliant( - expected_chain_name, - &cost_table, - &transaction_config, - MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + transaction.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp,), Err(expected_error) ); assert!( @@ -910,7 +1001,6 @@ mod tests { fn not_acceptable_due_to_excessive_ttl() { let rng = &mut TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); let transaction_config = TransactionConfig::default(); let ttl = transaction_config.max_ttl + TimeDiff::from(Duration::from_secs(1)); let transaction = TransactionV1Builder::new_random(rng) @@ -919,21 +1009,19 @@ mod tests { .build() .unwrap(); - let expected_error = TransactionV1ConfigFailure::ExcessiveTimeToLive { + let expected_error = InvalidTransactionV1::ExcessiveTimeToLive { max_ttl: transaction_config.max_ttl, got: ttl, }; let current_timestamp = transaction.timestamp(); + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret + }; assert_eq!( - transaction.is_config_compliant( - chain_name, - &cost_table, - &transaction_config, - MAX_ASSOCIATED_KEYS, - TimeDiff::default(), - current_timestamp - ), + transaction.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp,), Err(expected_error) ); assert!( @@ -946,8 +1034,6 @@ mod tests { fn not_acceptable_due_to_timestamp_in_future() { let rng = &mut TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let transaction_config = TransactionConfig::default(); let leeway = TimeDiff::from_seconds(2); let transaction = TransactionV1Builder::new_random(rng) @@ -956,21 +1042,20 @@ mod tests { .unwrap(); let current_timestamp = transaction.timestamp() - leeway - TimeDiff::from_seconds(1); - let expected_error = TransactionV1ConfigFailure::TimestampInFuture { + let expected_error = InvalidTransactionV1::TimestampInFuture { validation_timestamp: current_timestamp, timestamp_leeway: leeway, got: transaction.timestamp(), }; + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret + }; + assert_eq!( - transaction.is_config_compliant( - chain_name, - &cost_table, - &transaction_config, - MAX_ASSOCIATED_KEYS, - leeway, - current_timestamp - ), + transaction.is_config_compliant(&chainspec, leeway, current_timestamp), Err(expected_error) ); assert!( @@ -983,8 +1068,6 @@ mod tests { fn not_acceptable_due_to_excessive_approvals() { let rng = &mut TestRng::new(); let chain_name = "net-1"; - let cost_table = SystemConfig::default(); - let transaction_config = TransactionConfig::default(); let mut transaction = TransactionV1Builder::new_random(rng) .with_chain_name(chain_name) .build() @@ -996,25 +1079,290 @@ mod tests { let current_timestamp = transaction.timestamp(); - let expected_error = TransactionV1ConfigFailure::ExcessiveApprovals { + let expected_error = InvalidTransactionV1::ExcessiveApprovals { got: MAX_ASSOCIATED_KEYS + 1, max_associated_keys: MAX_ASSOCIATED_KEYS, }; + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret.core_config.max_associated_keys = MAX_ASSOCIATED_KEYS; + ret + }; + assert_eq!( - transaction.is_config_compliant( - chain_name, - &cost_table, - &transaction_config, - MAX_ASSOCIATED_KEYS, + transaction.is_config_compliant(&chainspec, TimeDiff::default(), current_timestamp,), + Err(expected_error) + ); + assert!( + transaction.is_verified.get().is_none(), + "transaction should not have run expensive `is_verified` call" + ); + } + + #[test] + fn not_acceptable_due_to_invalid_pricing_modes() { + let rng = &mut TestRng::new(); + let chain_name = "net-1"; + + let reserved_mode = PricingMode::Reserved { + receipt: Default::default(), + paid_amount: Default::default(), + strike_price: Default::default(), + }; + + let reserved_transaction = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(reserved_mode.clone()) + .build() + .expect("must be able to create a reserved transaction"); + + let chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret + }; + + let current_timestamp = reserved_transaction.timestamp(); + let expected_error = InvalidTransactionV1::InvalidPricingMode { + price_mode: reserved_mode, + }; + assert_eq!( + reserved_transaction.is_config_compliant( + &chainspec, + TimeDiff::default(), + current_timestamp, + ), + Err(expected_error) + ); + assert!( + reserved_transaction.is_verified.get().is_none(), + "transaction should not have run expensive `is_verified` call" + ); + + let fixed_mode_transaction = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(PricingMode::Fixed { + gas_price_tolerance: 1u8, + }) + .build() + .expect("must create fixed mode transaction"); + + let fixed_handling_chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret.core_config.pricing_handling = PricingHandling::Fixed; + ret + }; + + let classic_handling_chainspec = { + let mut ret = Chainspec::default(); + ret.network_config.name = chain_name.to_string(); + ret.core_config.pricing_handling = PricingHandling::Classic; + ret + }; + + let current_timestamp = fixed_mode_transaction.timestamp(); + let expected_error = InvalidTransactionV1::InvalidPricingMode { + price_mode: fixed_mode_transaction.pricing_mode().clone(), + }; + + assert_eq!( + fixed_mode_transaction.is_config_compliant( + &classic_handling_chainspec, + TimeDiff::default(), + current_timestamp, + ), + Err(expected_error) + ); + assert!( + fixed_mode_transaction.is_verified.get().is_none(), + "transaction should not have run expensive `is_verified` call" + ); + + assert!(fixed_mode_transaction + .is_config_compliant( + &fixed_handling_chainspec, TimeDiff::default(), current_timestamp + ) + .is_ok()); + + let classic_mode_transaction = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(PricingMode::Classic { + payment_amount: 100000, + gas_price_tolerance: 1, + standard_payment: true, + }) + .build() + .expect("must create classic transaction"); + + let current_timestamp = classic_mode_transaction.timestamp(); + let expected_error = InvalidTransactionV1::InvalidPricingMode { + price_mode: classic_mode_transaction.pricing_mode().clone(), + }; + + assert_eq!( + classic_mode_transaction.is_config_compliant( + &fixed_handling_chainspec, + TimeDiff::default(), + current_timestamp, ), Err(expected_error) ); assert!( - transaction.is_verified.get().is_none(), + classic_mode_transaction.is_verified.get().is_none(), "transaction should not have run expensive `is_verified` call" ); + + assert!(classic_mode_transaction + .is_config_compliant( + &classic_handling_chainspec, + TimeDiff::default(), + current_timestamp + ) + .is_ok()); + } + + #[test] + fn should_use_payment_amount_for_classic_payment() { + let payment_amount = 500u64; + let mut chainspec = Chainspec::default(); + let chain_name = "net-1"; + chainspec + .with_chain_name(chain_name.to_string()) + .with_pricing_handling(PricingHandling::Classic); + + let rng = &mut TestRng::new(); + let builder = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(PricingMode::Classic { + payment_amount, + gas_price_tolerance: 1, + standard_payment: true, + }); + let transaction = builder.build().expect("should build"); + let mut gas_price = 1; + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::from(payment_amount), + "in classic pricing, the user selected amount should be the cost if gas price is 1" + ); + gas_price += 1; + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::from(payment_amount) * gas_price, + "in classic pricing, the cost should == user selected amount * gas_price" + ); + } + + #[test] + fn should_use_cost_table_for_fixed_payment() { + let mut chainspec = Chainspec::default(); + let chain_name = "net-1"; + chainspec + .with_chain_name(chain_name.to_string()) + .with_pricing_handling(PricingHandling::Fixed); + + let rng = &mut TestRng::new(); + let builder = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(PricingMode::Fixed { + gas_price_tolerance: 5, + }); + let transaction = builder.build().expect("should build"); + let mut gas_price = 1; + let limit = transaction + .gas_limit(&chainspec) + .expect("should limit") + .value(); + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, limit, + "in fixed pricing, the cost & limit should == if gas price is 1" + ); + gas_price += 1; + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + limit * gas_price, + "in fixed pricing, the cost should == limit * gas_price" + ); + } + + #[test] + fn should_have_limit_but_no_cost_for_reserved() { + reserved_pricing(500u64, 1u8); + } + + #[test] + fn should_respect_strike_price_for_reserved() { + reserved_pricing(500u64, 2u8); + } + + #[cfg(test)] + fn reserved_pricing(paid_amount: u64, strike_price: u8) { + let mut chainspec = Chainspec::default(); + let chain_name = "net-1"; + chainspec + .with_chain_name(chain_name.to_string()) + .with_pricing_handling(PricingHandling::Fixed) + .with_allow_reservations(true); + + let rng = &mut TestRng::new(); + let builder = TransactionV1Builder::new_random(rng) + .with_chain_name(chain_name) + .with_pricing_mode(PricingMode::Reserved { + paid_amount, + strike_price, + receipt: Digest::default(), + }); + let transaction = builder.build().expect("should build"); + let mut gas_price = 1; + let limit = transaction + .gas_limit(&chainspec) + .expect("should limit") + .value() + .as_u64(); + assert_eq!( + limit, + paid_amount / strike_price as u64, + "in reserved pricing, limit should == paid_amount / strike price" + ); + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::zero(), + "in reserved pricing, cost should == 0 as it was prepaid" + ); + gas_price += 1; + let cost = transaction + .gas_cost(&chainspec, gas_price) + .expect("should cost") + .value(); + assert_eq!( + cost, + U512::zero(), + "in reserved pricing, gas price does not matter as it was prepaid" + ); } } diff --git a/types/src/transaction/transaction_v1/errors_v1.rs b/types/src/transaction/transaction_v1/errors_v1.rs index 74f361f054..690eb5bb97 100644 --- a/types/src/transaction/transaction_v1/errors_v1.rs +++ b/types/src/transaction/transaction_v1/errors_v1.rs @@ -1,4 +1,4 @@ -use alloc::{boxed::Box, string::String}; +use alloc::{boxed::Box, string::String, vec::Vec}; use core::{ array::TryFromSliceError, fmt::{self, Display, Formatter}, @@ -13,14 +13,14 @@ use serde::Serialize; use super::super::TransactionEntryPoint; #[cfg(doc)] use super::TransactionV1; -use crate::{crypto, CLType, TimeDiff, Timestamp, U512}; +use crate::{bytesrepr, crypto, CLType, DisplayIter, PricingMode, TimeDiff, Timestamp, U512}; /// Returned when a [`TransactionV1`] fails validation. #[derive(Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "std", derive(Serialize))] #[cfg_attr(feature = "datasize", derive(DataSize))] #[non_exhaustive] -pub enum TransactionV1ConfigFailure { +pub enum InvalidTransaction { /// Invalid chain name. InvalidChainName { /// The expected chain name. @@ -97,16 +97,24 @@ pub enum TransactionV1ConfigFailure { arg_name: String, }, - /// Given runtime arg is not expected type. + /// Given runtime arg is not one of the expected types. UnexpectedArgType { /// The name of the invalid arg. arg_name: String, - /// The expected type for the given runtime arg. - expected: CLType, + /// The choice of valid types for the given runtime arg. + expected: Vec, /// The provided type of the given runtime arg. got: CLType, }, + /// Failed to deserialize the given runtime arg. + InvalidArg { + /// The name of the invalid arg. + arg_name: String, + /// The deserialization error. + error: bytesrepr::Error, + }, + /// Insufficient transfer amount. InsufficientTransferAmount { /// The minimum transfer amount. @@ -126,30 +134,45 @@ pub enum TransactionV1ConfigFailure { /// The invalid entry point. entry_point: TransactionEntryPoint, }, - /// The transaction has empty module bytes. EmptyModuleBytes, + /// Attempt to factor the amount over the gas_price failed. + GasPriceConversion { + /// The base amount. + amount: u64, + /// The attempted gas price. + gas_price: u8, + }, + /// Unable to calculate gas limit. + UnableToCalculateGasLimit, + /// Unable to calculate gas cost. + UnableToCalculateGasCost, + /// Invalid combination of pricing handling and pricing mode. + InvalidPricingMode { + /// The pricing mode as specified by the transaction. + price_mode: PricingMode, + }, } -impl Display for TransactionV1ConfigFailure { +impl Display for InvalidTransaction { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { match self { - TransactionV1ConfigFailure::InvalidChainName { expected, got } => { + InvalidTransaction::InvalidChainName { expected, got } => { write!( formatter, "invalid chain name: expected {expected}, got {got}" ) } - TransactionV1ConfigFailure::ExcessiveSize(error) => { + InvalidTransaction::ExcessiveSize(error) => { write!(formatter, "transaction size too large: {error}") } - TransactionV1ConfigFailure::ExcessiveTimeToLive { max_ttl, got } => { + InvalidTransaction::ExcessiveTimeToLive { max_ttl, got } => { write!( formatter, "time-to-live of {got} exceeds limit of {max_ttl}" ) } - TransactionV1ConfigFailure::TimestampInFuture { + InvalidTransaction::TimestampInFuture { validation_timestamp, timestamp_leeway, got, @@ -160,35 +183,35 @@ impl Display for TransactionV1ConfigFailure { {validation_timestamp} plus leeway of {timestamp_leeway}" ) } - TransactionV1ConfigFailure::InvalidBodyHash => { + InvalidTransaction::InvalidBodyHash => { write!( formatter, "the provided hash does not match the actual hash of the transaction body" ) } - TransactionV1ConfigFailure::InvalidTransactionHash => { + InvalidTransaction::InvalidTransactionHash => { write!( formatter, "the provided hash does not match the actual hash of the transaction" ) } - TransactionV1ConfigFailure::EmptyApprovals => { + InvalidTransaction::EmptyApprovals => { write!(formatter, "the transaction has no approvals") } - TransactionV1ConfigFailure::InvalidApproval { index, error } => { + InvalidTransaction::InvalidApproval { index, error } => { write!( formatter, "the transaction approval at index {index} is invalid: {error}" ) } - TransactionV1ConfigFailure::ExcessiveArgsLength { max_length, got } => { + InvalidTransaction::ExcessiveArgsLength { max_length, got } => { write!( formatter, "serialized transaction runtime args of {got} bytes exceeds limit of \ {max_length} bytes" ) } - TransactionV1ConfigFailure::ExcessiveApprovals { + InvalidTransaction::ExcessiveApprovals { max_associated_keys, got, } => { @@ -198,7 +221,7 @@ impl Display for TransactionV1ConfigFailure { associated keys {max_associated_keys}", ) } - TransactionV1ConfigFailure::ExceedsBlockGasLimit { + InvalidTransaction::ExceedsBlockGasLimit { block_gas_limit, got, } => { @@ -207,65 +230,93 @@ impl Display for TransactionV1ConfigFailure { "payment amount of {got} exceeds the block gas limit of {block_gas_limit}" ) } - TransactionV1ConfigFailure::MissingArg { arg_name } => { + InvalidTransaction::MissingArg { arg_name } => { write!(formatter, "missing required runtime argument '{arg_name}'") } - TransactionV1ConfigFailure::UnexpectedArgType { + InvalidTransaction::UnexpectedArgType { arg_name, expected, got, } => { write!( formatter, - "expected type of '{arg_name}' runtime argument to be {expected}, but got {got}" + "expected type of '{arg_name}' runtime argument to be one of {}, but got {got}", + DisplayIter::new(expected) ) } - TransactionV1ConfigFailure::InsufficientTransferAmount { minimum, attempted } => { + InvalidTransaction::InvalidArg { arg_name, error } => { + write!(formatter, "invalid runtime argument '{arg_name}': {error}") + } + InvalidTransaction::InsufficientTransferAmount { minimum, attempted } => { write!( formatter, "insufficient transfer amount; minimum: {minimum} attempted: {attempted}" ) } - TransactionV1ConfigFailure::EntryPointCannotBeCustom { entry_point } => { + InvalidTransaction::EntryPointCannotBeCustom { entry_point } => { write!(formatter, "entry point cannot be custom: {entry_point}") } - TransactionV1ConfigFailure::EntryPointMustBeCustom { entry_point } => { + InvalidTransaction::EntryPointMustBeCustom { entry_point } => { write!(formatter, "entry point must be custom: {entry_point}") } - TransactionV1ConfigFailure::EmptyModuleBytes => { + InvalidTransaction::EmptyModuleBytes => { write!(formatter, "the transaction has empty module bytes") } + InvalidTransaction::GasPriceConversion { amount, gas_price } => { + write!( + formatter, + "failed to divide the amount {} by the gas price {}", + amount, gas_price + ) + } + InvalidTransaction::UnableToCalculateGasLimit => { + write!(formatter, "unable to calculate gas limit",) + } + InvalidTransaction::UnableToCalculateGasCost => { + write!(formatter, "unable to calculate gas cost",) + } + InvalidTransaction::InvalidPricingMode { price_mode } => { + write!( + formatter, + "received a transaction with an invalid mode {price_mode}" + ) + } } } } -impl From for TransactionV1ConfigFailure { +impl From for InvalidTransaction { fn from(error: ExcessiveSizeErrorV1) -> Self { - TransactionV1ConfigFailure::ExcessiveSize(error) + InvalidTransaction::ExcessiveSize(error) } } #[cfg(feature = "std")] -impl StdError for TransactionV1ConfigFailure { +impl StdError for InvalidTransaction { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { - TransactionV1ConfigFailure::InvalidApproval { error, .. } => Some(error), - TransactionV1ConfigFailure::InvalidChainName { .. } - | TransactionV1ConfigFailure::ExcessiveSize(_) - | TransactionV1ConfigFailure::ExcessiveTimeToLive { .. } - | TransactionV1ConfigFailure::TimestampInFuture { .. } - | TransactionV1ConfigFailure::InvalidBodyHash - | TransactionV1ConfigFailure::InvalidTransactionHash - | TransactionV1ConfigFailure::EmptyApprovals - | TransactionV1ConfigFailure::ExcessiveArgsLength { .. } - | TransactionV1ConfigFailure::ExcessiveApprovals { .. } - | TransactionV1ConfigFailure::ExceedsBlockGasLimit { .. } - | TransactionV1ConfigFailure::MissingArg { .. } - | TransactionV1ConfigFailure::UnexpectedArgType { .. } - | TransactionV1ConfigFailure::InsufficientTransferAmount { .. } - | TransactionV1ConfigFailure::EntryPointCannotBeCustom { .. } - | TransactionV1ConfigFailure::EntryPointMustBeCustom { .. } - | TransactionV1ConfigFailure::EmptyModuleBytes => None, + InvalidTransaction::InvalidApproval { error, .. } => Some(error), + InvalidTransaction::InvalidArg { error, .. } => Some(error), + InvalidTransaction::InvalidChainName { .. } + | InvalidTransaction::ExcessiveSize(_) + | InvalidTransaction::ExcessiveTimeToLive { .. } + | InvalidTransaction::TimestampInFuture { .. } + | InvalidTransaction::InvalidBodyHash + | InvalidTransaction::InvalidTransactionHash + | InvalidTransaction::EmptyApprovals + | InvalidTransaction::ExcessiveArgsLength { .. } + | InvalidTransaction::ExcessiveApprovals { .. } + | InvalidTransaction::ExceedsBlockGasLimit { .. } + | InvalidTransaction::MissingArg { .. } + | InvalidTransaction::UnexpectedArgType { .. } + | InvalidTransaction::InsufficientTransferAmount { .. } + | InvalidTransaction::EntryPointCannotBeCustom { .. } + | InvalidTransaction::EntryPointMustBeCustom { .. } + | InvalidTransaction::EmptyModuleBytes + | InvalidTransaction::GasPriceConversion { .. } + | InvalidTransaction::UnableToCalculateGasLimit + | InvalidTransaction::UnableToCalculateGasCost + | InvalidTransaction::InvalidPricingMode { .. } => None, } } } diff --git a/types/src/transaction/transaction_v1/transaction_v1_body.rs b/types/src/transaction/transaction_v1/transaction_v1_body.rs index df86bd616a..81295c4830 100644 --- a/types/src/transaction/transaction_v1/transaction_v1_body.rs +++ b/types/src/transaction/transaction_v1/transaction_v1_body.rs @@ -19,18 +19,22 @@ use super::super::{RuntimeArgs, TransactionEntryPoint, TransactionScheduling, Tr #[cfg(any(all(feature = "std", feature = "testing"), test))] use super::TransactionCategory; +#[cfg(any(feature = "std", test))] +use super::TransactionConfig; #[cfg(doc)] use super::TransactionV1; -#[cfg(any(feature = "std", test))] -use super::{TransactionConfig, TransactionV1ConfigFailure}; use crate::{ bytesrepr::{self, FromBytes, ToBytes}, TransactionSessionKind, }; +#[cfg(any(feature = "std", test))] +use crate::InvalidTransactionV1; + #[cfg(any(all(feature = "std", feature = "testing"), test))] use crate::{ bytesrepr::Bytes, testing::TestRng, PublicKey, TransactionInvocationTarget, TransactionRuntime, + TransferTarget, }; /// The body of a [`TransactionV1`]. @@ -74,6 +78,11 @@ impl TransactionV1Body { &self.args } + /// Consumes `self`, returning the runtime args of the transaction. + pub fn take_args(self) -> RuntimeArgs { + self.args + } + /// Returns the target of the transaction. pub fn target(&self) -> &TransactionTarget { &self.target @@ -89,13 +98,13 @@ impl TransactionV1Body { &self.scheduling } - /// This transaction is a native mint interaction. + /// Returns true if this transaction is a native mint interaction. pub fn is_native_mint(&self) -> bool { TransactionTarget::Native == self.target && TransactionEntryPoint::Transfer == self.entry_point } - /// This transaction is a native auction interaction. + /// Returns true if this transaction is a native auction interaction. pub fn is_native_auction(&self) -> bool { if TransactionTarget::Native != self.target { return false; @@ -111,7 +120,7 @@ impl TransactionV1Body { } } - /// This transaction is a smart contract installer or upgrader. + /// Returns true if this transaction is a smart contract installer or upgrader. pub fn is_install_or_upgrade(&self) -> bool { match self.target() { TransactionTarget::Native | TransactionTarget::Stored { .. } => false, @@ -122,16 +131,25 @@ impl TransactionV1Body { } } - /// This transaction goes into the misc / standard category. + /// Returns true if this transaction goes into the misc / standard category. pub fn is_standard(&self) -> bool { !self.is_native_mint() && !self.is_native_auction() && !self.is_install_or_upgrade() } + /// Consumes `self`, returning its constituent parts. + pub fn destructure( + self, + ) -> ( + RuntimeArgs, + TransactionTarget, + TransactionEntryPoint, + TransactionScheduling, + ) { + (self.args, self.target, self.entry_point, self.scheduling) + } + #[cfg(any(feature = "std", test))] - pub(super) fn is_valid( - &self, - config: &TransactionConfig, - ) -> Result<(), TransactionV1ConfigFailure> { + pub(super) fn is_valid(&self, config: &TransactionConfig) -> Result<(), InvalidTransactionV1> { let args_length = self.args.serialized_length(); if args_length > config.transaction_v1_config.max_args_length as usize { debug!( @@ -139,7 +157,7 @@ impl TransactionV1Body { max_args_length = config.transaction_v1_config.max_args_length, "transaction runtime args excessive size" ); - return Err(TransactionV1ConfigFailure::ExcessiveArgsLength { + return Err(InvalidTransactionV1::ExcessiveArgsLength { max_length: config.transaction_v1_config.max_args_length as usize, got: args_length, }); @@ -152,7 +170,7 @@ impl TransactionV1Body { entry_point = %self.entry_point, "native transaction cannot have custom entry point" ); - Err(TransactionV1ConfigFailure::EntryPointCannotBeCustom { + Err(InvalidTransactionV1::EntryPointCannotBeCustom { entry_point: self.entry_point.clone(), }) } @@ -190,7 +208,7 @@ impl TransactionV1Body { entry_point = %self.entry_point, "transaction targeting stored entity/package must have custom entry point" ); - Err(TransactionV1ConfigFailure::EntryPointMustBeCustom { + Err(InvalidTransactionV1::EntryPointMustBeCustom { entry_point: self.entry_point.clone(), }) } @@ -199,7 +217,7 @@ impl TransactionV1Body { TransactionEntryPoint::Custom(_) => { if module_bytes.is_empty() { debug!("transaction with session code must not have empty module bytes"); - return Err(TransactionV1ConfigFailure::EmptyModuleBytes); + return Err(InvalidTransactionV1::EmptyModuleBytes); } Ok(()) } @@ -214,7 +232,7 @@ impl TransactionV1Body { entry_point = %self.entry_point, "transaction with session code must have custom entry point" ); - Err(TransactionV1ConfigFailure::EntryPointMustBeCustom { + Err(InvalidTransactionV1::EntryPointMustBeCustom { entry_point: self.entry_point.clone(), }) } @@ -235,14 +253,12 @@ impl TransactionV1Body { #[cfg(any(all(feature = "std", feature = "testing"), test))] fn random_transfer(rng: &mut TestRng) -> Self { - let source = rng.gen(); - let target = rng.gen(); let amount = rng.gen_range(TransactionConfig::default().native_transfer_minimum_motes..=u64::MAX); - let maybe_to = rng.gen::().then(|| rng.gen()); + let maybe_source = if rng.gen() { Some(rng.gen()) } else { None }; + let target = TransferTarget::random(rng); let maybe_id = rng.gen::().then(|| rng.gen()); - let args = - arg_handling::new_transfer_args(source, target, amount, maybe_to, maybe_id).unwrap(); + let args = arg_handling::new_transfer_args(amount, maybe_source, target, maybe_id).unwrap(); TransactionV1Body::new( args, TransactionTarget::Native, @@ -267,11 +283,9 @@ impl TransactionV1Body { #[cfg(any(all(feature = "std", feature = "testing"), test))] fn random_install_upgrade(rng: &mut TestRng) -> Self { - let mut buffer = vec![0u8; rng.gen_range(0..100)]; - rng.fill_bytes(buffer.as_mut()); let target = TransactionTarget::Session { kind: TransactionSessionKind::Upgrader, - module_bytes: Bytes::from(buffer), + module_bytes: Bytes::from(rng.random_vec(0..100)), runtime: TransactionRuntime::VmCasperV1, }; TransactionV1Body::new( @@ -284,14 +298,10 @@ impl TransactionV1Body { #[cfg(any(all(feature = "std", feature = "testing"), test))] fn random_staking(rng: &mut TestRng) -> Self { - let source = rng.gen(); - let target = rng.gen(); - let amount = - rng.gen_range(TransactionConfig::default().native_transfer_minimum_motes..=u64::MAX); - let maybe_to = rng.gen::().then(|| rng.gen()); - let maybe_id = rng.gen::().then(|| rng.gen()); - let args = - arg_handling::new_transfer_args(source, target, amount, maybe_to, maybe_id).unwrap(); + let public_key = PublicKey::random(rng); + let delegation_rate = rng.gen(); + let amount = rng.gen::(); + let args = arg_handling::new_add_bid_args(public_key, delegation_rate, amount).unwrap(); TransactionV1Body::new( args, TransactionTarget::Native, @@ -304,7 +314,22 @@ impl TransactionV1Body { #[cfg(any(all(feature = "std", feature = "testing"), test))] pub fn random(rng: &mut TestRng) -> Self { match rng.gen_range(0..8) { - 0 => Self::random_transfer(rng), + 0 => { + let amount = rng.gen_range( + TransactionConfig::default().native_transfer_minimum_motes..=u64::MAX, + ); + let maybe_source = if rng.gen() { Some(rng.gen()) } else { None }; + let target = TransferTarget::random(rng); + let maybe_id = rng.gen::().then(|| rng.gen()); + let args = arg_handling::new_transfer_args(amount, maybe_source, target, maybe_id) + .unwrap(); + TransactionV1Body::new( + args, + TransactionTarget::Native, + TransactionEntryPoint::Transfer, + TransactionScheduling::random(rng), + ) + } 1 => { let public_key = PublicKey::random(rng); let delegation_rate = rng.gen(); @@ -400,13 +425,6 @@ impl Display for TransactionV1Body { } impl ToBytes for TransactionV1Body { - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - self.args.write_bytes(writer)?; - self.target.write_bytes(writer)?; - self.entry_point.write_bytes(writer)?; - self.scheduling.write_bytes(writer) - } - fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; @@ -419,6 +437,13 @@ impl ToBytes for TransactionV1Body { + self.entry_point.serialized_length() + self.scheduling.serialized_length() } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.args.write_bytes(writer)?; + self.target.write_bytes(writer)?; + self.entry_point.write_bytes(writer)?; + self.scheduling.write_bytes(writer) + } } impl FromBytes for TransactionV1Body { @@ -452,7 +477,7 @@ mod tests { let mut body = TransactionV1Body::random(rng); body.args = runtime_args! {"a" => 1_u8}; - let expected_error = TransactionV1ConfigFailure::ExcessiveArgsLength { + let expected_error = InvalidTransactionV1::ExcessiveArgsLength { max_length: 10, got: 15, }; @@ -474,7 +499,7 @@ mod tests { TransactionScheduling::random(rng), ); - let expected_error = TransactionV1ConfigFailure::EntryPointCannotBeCustom { entry_point }; + let expected_error = InvalidTransactionV1::EntryPointCannotBeCustom { entry_point }; let config = TransactionConfig::default(); assert_eq!(body.is_valid(&config,), Err(expected_error)); @@ -487,7 +512,7 @@ mod tests { let mut check = |entry_point: TransactionEntryPoint| { let stored_target = TransactionTarget::new_stored( - TransactionInvocationTarget::InvocableEntity([0; 32]), + TransactionInvocationTarget::ByHash([0; 32]), TransactionRuntime::VmCasperV1, ); let session_target = TransactionTarget::new_session( @@ -509,7 +534,7 @@ mod tests { TransactionScheduling::random(rng), ); - let expected_error = TransactionV1ConfigFailure::EntryPointMustBeCustom { entry_point }; + let expected_error = InvalidTransactionV1::EntryPointMustBeCustom { entry_point }; assert_eq!(stored_body.is_valid(&config,), Err(expected_error.clone())); assert_eq!(session_body.is_valid(&config,), Err(expected_error)); diff --git a/types/src/transaction/transaction_v1/transaction_v1_body/arg_handling.rs b/types/src/transaction/transaction_v1/transaction_v1_body/arg_handling.rs index 7a99a942b9..7e4cbcaa1a 100644 --- a/types/src/transaction/transaction_v1/transaction_v1_body/arg_handling.rs +++ b/types/src/transaction/transaction_v1/transaction_v1_body/arg_handling.rs @@ -2,18 +2,17 @@ use core::marker::PhantomData; use tracing::debug; -use super::super::TransactionV1ConfigFailure; use crate::{ account::AccountHash, bytesrepr::{FromBytes, ToBytes}, - system::auction::ARG_VALIDATOR_PUBLIC_KEY, - CLTyped, CLValue, CLValueError, PublicKey, RuntimeArgs, URef, U512, + system::auction::ARG_VALIDATOR, + CLType, CLTyped, CLValue, CLValueError, InvalidTransactionV1, PublicKey, RuntimeArgs, + TransferTarget, URef, U512, }; -const TRANSFER_ARG_SOURCE: RequiredArg = RequiredArg::new("source"); -const TRANSFER_ARG_TARGET: RequiredArg = RequiredArg::new("target"); const TRANSFER_ARG_AMOUNT: RequiredArg = RequiredArg::new("amount"); -const TRANSFER_ARG_TO: OptionalArg = OptionalArg::new("to"); +const TRANSFER_ARG_SOURCE: OptionalArg = OptionalArg::new("source"); +const TRANSFER_ARG_TARGET: &str = "target"; const TRANSFER_ARG_ID: OptionalArg = OptionalArg::new("id"); const ADD_BID_ARG_PUBLIC_KEY: RequiredArg = RequiredArg::new("public_key"); @@ -36,8 +35,7 @@ const REDELEGATE_ARG_VALIDATOR: RequiredArg = RequiredArg::new("valid const REDELEGATE_ARG_AMOUNT: RequiredArg = RequiredArg::new("amount"); const REDELEGATE_ARG_NEW_VALIDATOR: RequiredArg = RequiredArg::new("new_validator"); -const ACTIVATE_BID_ARG_VALIDATOR: RequiredArg = - RequiredArg::new(ARG_VALIDATOR_PUBLIC_KEY); +const ACTIVATE_BID_ARG_VALIDATOR: RequiredArg = RequiredArg::new(ARG_VALIDATOR); struct RequiredArg { name: &'static str, @@ -52,13 +50,13 @@ impl RequiredArg { } } - fn get(&self, args: &RuntimeArgs) -> Result + fn get(&self, args: &RuntimeArgs) -> Result where T: CLTyped + FromBytes, { let cl_value = args.get(self.name).ok_or_else(|| { debug!("missing required runtime argument '{}'", self.name); - TransactionV1ConfigFailure::MissingArg { + InvalidTransactionV1::MissingArg { arg_name: self.name.to_string(), } })?; @@ -86,7 +84,7 @@ impl OptionalArg { } } - fn get(&self, args: &RuntimeArgs) -> Result, TransactionV1ConfigFailure> + fn get(&self, args: &RuntimeArgs) -> Result, InvalidTransactionV1> where T: CLTyped + FromBytes, { @@ -109,36 +107,46 @@ impl OptionalArg { fn parse_cl_value( cl_value: &CLValue, arg_name: &str, -) -> Result { - cl_value.to_t::().map_err(|_| { - debug!( - "expected runtime argument '{arg_name}' to be of type {}, but is {}", - T::cl_type(), - cl_value.cl_type() - ); - TransactionV1ConfigFailure::UnexpectedArgType { - arg_name: arg_name.to_string(), - expected: T::cl_type(), - got: cl_value.cl_type().clone(), - } +) -> Result { + cl_value.to_t::().map_err(|error| { + let error = match error { + CLValueError::Serialization(error) => InvalidTransactionV1::InvalidArg { + arg_name: arg_name.to_string(), + error, + }, + CLValueError::Type(_) => InvalidTransactionV1::UnexpectedArgType { + arg_name: arg_name.to_string(), + expected: vec![T::cl_type()], + got: cl_value.cl_type().clone(), + }, + }; + debug!("{error}"); + error }) } /// Creates a `RuntimeArgs` suitable for use in a transfer transaction. -pub(in crate::transaction::transaction_v1) fn new_transfer_args>( - source: URef, - target: URef, +pub(in crate::transaction::transaction_v1) fn new_transfer_args< + A: Into, + T: Into, +>( amount: A, - maybe_to: Option, + maybe_source: Option, + target: T, maybe_id: Option, ) -> Result { let mut args = RuntimeArgs::new(); - TRANSFER_ARG_SOURCE.insert(&mut args, source)?; - TRANSFER_ARG_TARGET.insert(&mut args, target)?; - TRANSFER_ARG_AMOUNT.insert(&mut args, amount.into())?; - if let Some(to) = maybe_to { - TRANSFER_ARG_TO.insert(&mut args, to)?; + if let Some(source) = maybe_source { + TRANSFER_ARG_SOURCE.insert(&mut args, source)?; } + match target.into() { + TransferTarget::PublicKey(public_key) => args.insert(TRANSFER_ARG_TARGET, public_key)?, + TransferTarget::AccountHash(account_hash) => { + args.insert(TRANSFER_ARG_TARGET, account_hash)? + } + TransferTarget::URef(uref) => args.insert(TRANSFER_ARG_TARGET, uref)?, + } + TRANSFER_ARG_AMOUNT.insert(&mut args, amount.into())?; if let Some(id) = maybe_id { TRANSFER_ARG_ID.insert(&mut args, id)?; } @@ -149,9 +157,7 @@ pub(in crate::transaction::transaction_v1) fn new_transfer_args>( pub(in crate::transaction::transaction_v1) fn has_valid_transfer_args( args: &RuntimeArgs, native_transfer_minimum_motes: u64, -) -> Result<(), TransactionV1ConfigFailure> { - let _source = TRANSFER_ARG_SOURCE.get(args)?; - let _target = TRANSFER_ARG_TARGET.get(args)?; +) -> Result<(), InvalidTransactionV1> { let amount = TRANSFER_ARG_AMOUNT.get(args)?; if amount < U512::from(native_transfer_minimum_motes) { debug!( @@ -159,12 +165,46 @@ pub(in crate::transaction::transaction_v1) fn has_valid_transfer_args( %amount, "insufficient transfer amount" ); - return Err(TransactionV1ConfigFailure::InsufficientTransferAmount { + return Err(InvalidTransactionV1::InsufficientTransferAmount { minimum: native_transfer_minimum_motes, attempted: amount, }); } - let _maybe_to = TRANSFER_ARG_TO.get(args)?; + let _source = TRANSFER_ARG_SOURCE.get(args)?; + + let target_cl_value = args.get(TRANSFER_ARG_TARGET).ok_or_else(|| { + debug!("missing required runtime argument '{TRANSFER_ARG_TARGET}'"); + InvalidTransactionV1::MissingArg { + arg_name: TRANSFER_ARG_TARGET.to_string(), + } + })?; + match target_cl_value.cl_type() { + CLType::PublicKey => { + let _ = parse_cl_value::(target_cl_value, TRANSFER_ARG_TARGET); + } + CLType::ByteArray(32) => { + let _ = parse_cl_value::(target_cl_value, TRANSFER_ARG_TARGET); + } + CLType::URef => { + let _ = parse_cl_value::(target_cl_value, TRANSFER_ARG_TARGET); + } + _ => { + debug!( + "expected runtime argument '{TRANSFER_ARG_TARGET}' to be of type {}, {} or {}, + but is {}", + CLType::PublicKey, + CLType::ByteArray(32), + CLType::URef, + target_cl_value.cl_type() + ); + return Err(InvalidTransactionV1::UnexpectedArgType { + arg_name: TRANSFER_ARG_TARGET.to_string(), + expected: vec![CLType::PublicKey, CLType::ByteArray(32), CLType::URef], + got: target_cl_value.cl_type().clone(), + }); + } + } + let _maybe_id = TRANSFER_ARG_ID.get(args)?; Ok(()) } @@ -185,7 +225,7 @@ pub(in crate::transaction::transaction_v1) fn new_add_bid_args>( /// Checks the given `RuntimeArgs` are suitable for use in an add_bid transaction. pub(in crate::transaction::transaction_v1) fn has_valid_add_bid_args( args: &RuntimeArgs, -) -> Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _public_key = ADD_BID_ARG_PUBLIC_KEY.get(args)?; let _delegation_rate = ADD_BID_ARG_DELEGATION_RATE.get(args)?; let _amount = ADD_BID_ARG_AMOUNT.get(args)?; @@ -206,7 +246,7 @@ pub(in crate::transaction::transaction_v1) fn new_withdraw_bid_args Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _public_key = WITHDRAW_BID_ARG_PUBLIC_KEY.get(args)?; let _amount = WITHDRAW_BID_ARG_AMOUNT.get(args)?; Ok(()) @@ -228,7 +268,7 @@ pub(in crate::transaction::transaction_v1) fn new_delegate_args>( /// Checks the given `RuntimeArgs` are suitable for use in a delegate transaction. pub(in crate::transaction::transaction_v1) fn has_valid_delegate_args( args: &RuntimeArgs, -) -> Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _delegator = DELEGATE_ARG_DELEGATOR.get(args)?; let _validator = DELEGATE_ARG_VALIDATOR.get(args)?; let _amount = DELEGATE_ARG_AMOUNT.get(args)?; @@ -251,7 +291,7 @@ pub(in crate::transaction::transaction_v1) fn new_undelegate_args> /// Checks the given `RuntimeArgs` are suitable for use in an undelegate transaction. pub(in crate::transaction::transaction_v1) fn has_valid_undelegate_args( args: &RuntimeArgs, -) -> Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _delegator = UNDELEGATE_ARG_DELEGATOR.get(args)?; let _validator = UNDELEGATE_ARG_VALIDATOR.get(args)?; let _amount = UNDELEGATE_ARG_AMOUNT.get(args)?; @@ -276,7 +316,7 @@ pub(in crate::transaction::transaction_v1) fn new_redelegate_args> /// Checks the given `RuntimeArgs` are suitable for use in a redelegate transaction. pub(in crate::transaction::transaction_v1) fn has_valid_redelegate_args( args: &RuntimeArgs, -) -> Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _delegator = REDELEGATE_ARG_DELEGATOR.get(args)?; let _validator = REDELEGATE_ARG_VALIDATOR.get(args)?; let _amount = REDELEGATE_ARG_AMOUNT.get(args)?; @@ -287,7 +327,7 @@ pub(in crate::transaction::transaction_v1) fn has_valid_redelegate_args( /// Checks the given `RuntimeArgs` are suitable for use in a redelegate transaction. pub(in crate::transaction::transaction_v1) fn has_valid_activate_bid_args( args: &RuntimeArgs, -) -> Result<(), TransactionV1ConfigFailure> { +) -> Result<(), InvalidTransactionV1> { let _validator = ACTIVATE_BID_ARG_VALIDATOR.get(args)?; Ok(()) } @@ -303,12 +343,31 @@ mod tests { fn should_validate_transfer_args() { let rng = &mut TestRng::new(); let min_motes = 10_u64; - // Check random args, within motes limit. + // Check random args, PublicKey target, within motes limit. + let args = new_transfer_args( + U512::from(rng.gen_range(min_motes..=u64::MAX)), + rng.gen::().then(|| rng.gen()), + PublicKey::random(rng), + rng.gen::().then(|| rng.gen()), + ) + .unwrap(); + has_valid_transfer_args(&args, min_motes).unwrap(); + + // Check random args, AccountHash target, within motes limit. let args = new_transfer_args( - rng.gen(), - rng.gen(), U512::from(rng.gen_range(min_motes..=u64::MAX)), rng.gen::().then(|| rng.gen()), + rng.gen::(), + rng.gen::().then(|| rng.gen()), + ) + .unwrap(); + has_valid_transfer_args(&args, min_motes).unwrap(); + + // Check random args, URef target, within motes limit. + let args = new_transfer_args( + U512::from(rng.gen_range(min_motes..=u64::MAX)), + rng.gen::().then(|| rng.gen()), + rng.gen::(), rng.gen::().then(|| rng.gen()), ) .unwrap(); @@ -316,10 +375,9 @@ mod tests { // Check at minimum motes limit. let args = new_transfer_args( - rng.gen(), - rng.gen(), U512::from(min_motes), rng.gen::().then(|| rng.gen()), + PublicKey::random(rng), rng.gen::().then(|| rng.gen()), ) .unwrap(); @@ -327,10 +385,9 @@ mod tests { // Check with extra arg. let mut args = new_transfer_args( - rng.gen(), - rng.gen(), U512::from(min_motes), rng.gen::().then(|| rng.gen()), + PublicKey::random(rng), rng.gen::().then(|| rng.gen()), ) .unwrap(); @@ -344,12 +401,11 @@ mod tests { let min_motes = 10_u64; let args = runtime_args! { - TRANSFER_ARG_SOURCE.name => rng.gen::(), - TRANSFER_ARG_TARGET.name => rng.gen::(), - TRANSFER_ARG_AMOUNT.name => U512::from(min_motes - 1) + TRANSFER_ARG_AMOUNT.name => U512::from(min_motes - 1), + TRANSFER_ARG_TARGET => PublicKey::random(rng) }; - let expected_error = TransactionV1ConfigFailure::InsufficientTransferAmount { + let expected_error = InvalidTransactionV1::InsufficientTransferAmount { minimum: min_motes, attempted: U512::from(min_motes - 1), }; @@ -365,26 +421,12 @@ mod tests { let rng = &mut TestRng::new(); let min_motes = 10_u64; - // Missing "source". - let args = runtime_args! { - TRANSFER_ARG_TARGET.name => rng.gen::(), - TRANSFER_ARG_AMOUNT.name => U512::from(min_motes) - }; - let expected_error = TransactionV1ConfigFailure::MissingArg { - arg_name: TRANSFER_ARG_SOURCE.name.to_string(), - }; - assert_eq!( - has_valid_transfer_args(&args, min_motes), - Err(expected_error) - ); - // Missing "target". let args = runtime_args! { - TRANSFER_ARG_SOURCE.name => rng.gen::(), - TRANSFER_ARG_AMOUNT.name => U512::from(min_motes) + TRANSFER_ARG_AMOUNT.name => U512::from(min_motes), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { - arg_name: TRANSFER_ARG_TARGET.name.to_string(), + let expected_error = InvalidTransactionV1::MissingArg { + arg_name: TRANSFER_ARG_TARGET.to_string(), }; assert_eq!( has_valid_transfer_args(&args, min_motes), @@ -393,10 +435,9 @@ mod tests { // Missing "amount". let args = runtime_args! { - TRANSFER_ARG_SOURCE.name => rng.gen::(), - TRANSFER_ARG_TARGET.name => rng.gen::() + TRANSFER_ARG_TARGET => PublicKey::random(rng) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: TRANSFER_ARG_AMOUNT.name.to_string(), }; assert_eq!( @@ -410,32 +451,30 @@ mod tests { let rng = &mut TestRng::new(); let min_motes = 10_u64; - // Wrong "source" type (a required arg). + // Wrong "target" type (a required arg). let args = runtime_args! { - TRANSFER_ARG_SOURCE.name => 1_u8, - TRANSFER_ARG_TARGET.name => rng.gen::(), - TRANSFER_ARG_AMOUNT.name => U512::from(min_motes) + TRANSFER_ARG_AMOUNT.name => U512::from(min_motes), + TRANSFER_ARG_TARGET => "wrong" }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { - arg_name: TRANSFER_ARG_SOURCE.name.to_string(), - expected: CLType::URef, - got: CLType::U8, + let expected_error = InvalidTransactionV1::UnexpectedArgType { + arg_name: TRANSFER_ARG_TARGET.to_string(), + expected: vec![CLType::PublicKey, CLType::ByteArray(32), CLType::URef], + got: CLType::String, }; assert_eq!( has_valid_transfer_args(&args, min_motes), Err(expected_error) ); - // Wrong "to" type (an optional arg). + // Wrong "source" type (an optional arg). let args = runtime_args! { - TRANSFER_ARG_SOURCE.name => rng.gen::(), - TRANSFER_ARG_TARGET.name => rng.gen::(), TRANSFER_ARG_AMOUNT.name => U512::from(min_motes), - TRANSFER_ARG_TO.name => 1_u8 + TRANSFER_ARG_SOURCE.name => 1_u8, + TRANSFER_ARG_TARGET => PublicKey::random(rng) }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { - arg_name: TRANSFER_ARG_TO.name.to_string(), - expected: Option::::cl_type(), + let expected_error = InvalidTransactionV1::UnexpectedArgType { + arg_name: TRANSFER_ARG_SOURCE.name.to_string(), + expected: vec![Option::::cl_type()], got: CLType::U8, }; assert_eq!( @@ -467,7 +506,7 @@ mod tests { ADD_BID_ARG_DELEGATION_RATE.name => rng.gen::(), ADD_BID_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: ADD_BID_ARG_PUBLIC_KEY.name.to_string(), }; assert_eq!(has_valid_add_bid_args(&args), Err(expected_error)); @@ -477,7 +516,7 @@ mod tests { ADD_BID_ARG_PUBLIC_KEY.name => PublicKey::random(rng), ADD_BID_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: ADD_BID_ARG_DELEGATION_RATE.name.to_string(), }; assert_eq!(has_valid_add_bid_args(&args), Err(expected_error)); @@ -487,7 +526,7 @@ mod tests { ADD_BID_ARG_PUBLIC_KEY.name => PublicKey::random(rng), ADD_BID_ARG_DELEGATION_RATE.name => rng.gen::() }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: ADD_BID_ARG_AMOUNT.name.to_string(), }; assert_eq!(has_valid_add_bid_args(&args), Err(expected_error)); @@ -503,9 +542,9 @@ mod tests { ADD_BID_ARG_DELEGATION_RATE.name => rng.gen::(), ADD_BID_ARG_AMOUNT.name => rng.gen::() }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { + let expected_error = InvalidTransactionV1::UnexpectedArgType { arg_name: ADD_BID_ARG_AMOUNT.name.to_string(), - expected: CLType::U512, + expected: vec![CLType::U512], got: CLType::U64, }; assert_eq!(has_valid_add_bid_args(&args), Err(expected_error)); @@ -532,7 +571,7 @@ mod tests { let args = runtime_args! { WITHDRAW_BID_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: WITHDRAW_BID_ARG_PUBLIC_KEY.name.to_string(), }; assert_eq!(has_valid_withdraw_bid_args(&args), Err(expected_error)); @@ -541,7 +580,7 @@ mod tests { let args = runtime_args! { WITHDRAW_BID_ARG_PUBLIC_KEY.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: WITHDRAW_BID_ARG_AMOUNT.name.to_string(), }; assert_eq!(has_valid_withdraw_bid_args(&args), Err(expected_error)); @@ -556,9 +595,9 @@ mod tests { WITHDRAW_BID_ARG_PUBLIC_KEY.name => PublicKey::random(rng), WITHDRAW_BID_ARG_AMOUNT.name => rng.gen::() }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { + let expected_error = InvalidTransactionV1::UnexpectedArgType { arg_name: WITHDRAW_BID_ARG_AMOUNT.name.to_string(), - expected: CLType::U512, + expected: vec![CLType::U512], got: CLType::U64, }; assert_eq!(has_valid_withdraw_bid_args(&args), Err(expected_error)); @@ -591,7 +630,7 @@ mod tests { DELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), DELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: DELEGATE_ARG_DELEGATOR.name.to_string(), }; assert_eq!(has_valid_delegate_args(&args), Err(expected_error)); @@ -601,7 +640,7 @@ mod tests { DELEGATE_ARG_DELEGATOR.name => PublicKey::random(rng), DELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: DELEGATE_ARG_VALIDATOR.name.to_string(), }; assert_eq!(has_valid_delegate_args(&args), Err(expected_error)); @@ -611,7 +650,7 @@ mod tests { DELEGATE_ARG_DELEGATOR.name => PublicKey::random(rng), DELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: DELEGATE_ARG_AMOUNT.name.to_string(), }; assert_eq!(has_valid_delegate_args(&args), Err(expected_error)); @@ -627,9 +666,9 @@ mod tests { DELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), DELEGATE_ARG_AMOUNT.name => rng.gen::() }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { + let expected_error = InvalidTransactionV1::UnexpectedArgType { arg_name: DELEGATE_ARG_AMOUNT.name.to_string(), - expected: CLType::U512, + expected: vec![CLType::U512], got: CLType::U64, }; assert_eq!(has_valid_delegate_args(&args), Err(expected_error)); @@ -662,7 +701,7 @@ mod tests { UNDELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), UNDELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: UNDELEGATE_ARG_DELEGATOR.name.to_string(), }; assert_eq!(has_valid_undelegate_args(&args), Err(expected_error)); @@ -672,7 +711,7 @@ mod tests { UNDELEGATE_ARG_DELEGATOR.name => PublicKey::random(rng), UNDELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()) }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: UNDELEGATE_ARG_VALIDATOR.name.to_string(), }; assert_eq!(has_valid_undelegate_args(&args), Err(expected_error)); @@ -682,7 +721,7 @@ mod tests { UNDELEGATE_ARG_DELEGATOR.name => PublicKey::random(rng), UNDELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: UNDELEGATE_ARG_AMOUNT.name.to_string(), }; assert_eq!(has_valid_undelegate_args(&args), Err(expected_error)); @@ -698,9 +737,9 @@ mod tests { UNDELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), UNDELEGATE_ARG_AMOUNT.name => rng.gen::() }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { + let expected_error = InvalidTransactionV1::UnexpectedArgType { arg_name: UNDELEGATE_ARG_AMOUNT.name.to_string(), - expected: CLType::U512, + expected: vec![CLType::U512], got: CLType::U64, }; assert_eq!(has_valid_undelegate_args(&args), Err(expected_error)); @@ -735,7 +774,7 @@ mod tests { REDELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()), REDELEGATE_ARG_NEW_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: REDELEGATE_ARG_DELEGATOR.name.to_string(), }; assert_eq!(has_valid_redelegate_args(&args), Err(expected_error)); @@ -746,7 +785,7 @@ mod tests { REDELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()), REDELEGATE_ARG_NEW_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: REDELEGATE_ARG_VALIDATOR.name.to_string(), }; assert_eq!(has_valid_redelegate_args(&args), Err(expected_error)); @@ -757,7 +796,7 @@ mod tests { REDELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), REDELEGATE_ARG_NEW_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: REDELEGATE_ARG_AMOUNT.name.to_string(), }; assert_eq!(has_valid_redelegate_args(&args), Err(expected_error)); @@ -768,7 +807,7 @@ mod tests { REDELEGATE_ARG_VALIDATOR.name => PublicKey::random(rng), REDELEGATE_ARG_AMOUNT.name => U512::from(rng.gen::()), }; - let expected_error = TransactionV1ConfigFailure::MissingArg { + let expected_error = InvalidTransactionV1::MissingArg { arg_name: REDELEGATE_ARG_NEW_VALIDATOR.name.to_string(), }; assert_eq!(has_valid_redelegate_args(&args), Err(expected_error)); @@ -785,9 +824,9 @@ mod tests { REDELEGATE_ARG_AMOUNT.name => rng.gen::(), REDELEGATE_ARG_NEW_VALIDATOR.name => PublicKey::random(rng), }; - let expected_error = TransactionV1ConfigFailure::UnexpectedArgType { + let expected_error = InvalidTransactionV1::UnexpectedArgType { arg_name: REDELEGATE_ARG_AMOUNT.name.to_string(), - expected: CLType::U512, + expected: vec![CLType::U512], got: CLType::U64, }; assert_eq!(has_valid_redelegate_args(&args), Err(expected_error)); diff --git a/types/src/transaction/transaction_v1/transaction_v1_builder.rs b/types/src/transaction/transaction_v1/transaction_v1_builder.rs index d45776abc2..41516d2fba 100644 --- a/types/src/transaction/transaction_v1/transaction_v1_builder.rs +++ b/types/src/transaction/transaction_v1/transaction_v1_builder.rs @@ -14,8 +14,8 @@ use super::{ InitiatorAddrAndSecretKey, PricingMode, TransactionV1, TransactionV1Body, }; use crate::{ - account::AccountHash, bytesrepr::Bytes, CLValue, CLValueError, EntityAddr, EntityVersion, - PackageAddr, PublicKey, RuntimeArgs, SecretKey, TimeDiff, Timestamp, URef, U512, + bytesrepr::Bytes, AddressableEntityHash, CLValue, CLValueError, EntityVersion, PackageHash, + PublicKey, RuntimeArgs, SecretKey, TimeDiff, Timestamp, TransferTarget, URef, U512, }; #[cfg(any(feature = "testing", test))] use crate::{ @@ -81,14 +81,13 @@ impl<'a> TransactionV1Builder<'a> { } /// Returns a new `TransactionV1Builder` suitable for building a native transfer transaction. - pub fn new_transfer>( - source: URef, - target: URef, + pub fn new_transfer, T: Into>( amount: A, - maybe_to: Option, + maybe_source: Option, + target: T, maybe_id: Option, ) -> Result { - let args = arg_handling::new_transfer_args(source, target, amount, maybe_to, maybe_id)?; + let args = arg_handling::new_transfer_args(amount, maybe_source, target, maybe_id)?; let body = TransactionV1Body::new( args, TransactionTarget::Native, @@ -199,10 +198,10 @@ impl<'a> TransactionV1Builder<'a> { /// Returns a new `TransactionV1Builder` suitable for building a transaction targeting a stored /// entity. pub fn new_targeting_invocable_entity>( - addr: EntityAddr, + hash: AddressableEntityHash, entry_point: E, ) -> Self { - let id = TransactionInvocationTarget::new_invocable_entity(addr.value()); + let id = TransactionInvocationTarget::new_invocable_entity(hash); Self::new_targeting_stored(id, entry_point) } @@ -219,11 +218,11 @@ impl<'a> TransactionV1Builder<'a> { /// Returns a new `TransactionV1Builder` suitable for building a transaction targeting a /// package. pub fn new_targeting_package>( - addr: PackageAddr, + hash: PackageHash, version: Option, entry_point: E, ) -> Self { - let id = TransactionInvocationTarget::new_package(addr, version); + let id = TransactionInvocationTarget::new_package(hash, version); Self::new_targeting_stored(id, entry_point) } @@ -355,8 +354,8 @@ impl<'a> TransactionV1Builder<'a> { /// /// If not provided, the public key derived from the secret key used in the builder will be /// used as the `InitiatorAddr::PublicKey` in the transaction. - pub fn with_initiator_addr(mut self, initiator_addr: InitiatorAddr) -> Self { - self.initiator_addr = Some(initiator_addr); + pub fn with_initiator_addr>(mut self, initiator_addr: I) -> Self { + self.initiator_addr = Some(initiator_addr.into()); self } diff --git a/types/src/transaction/transaction_v1/transaction_v1_hash.rs b/types/src/transaction/transaction_v1/transaction_v1_hash.rs index c7ba947d66..86908478d1 100644 --- a/types/src/transaction/transaction_v1/transaction_v1_hash.rs +++ b/types/src/transaction/transaction_v1/transaction_v1_hash.rs @@ -47,7 +47,6 @@ impl TransactionV1Hash { /// Returns a new `TransactionV1Hash` directly initialized with the provided bytes; no hashing /// is done. - #[cfg(any(feature = "testing", test))] pub const fn from_raw(raw_digest: [u8; Self::LENGTH]) -> Self { TransactionV1Hash(Digest::from_raw(raw_digest)) } diff --git a/types/src/transaction/transaction_v1/transaction_v1_header.rs b/types/src/transaction/transaction_v1/transaction_v1_header.rs index 58c8398a1b..6dbcb43123 100644 --- a/types/src/transaction/transaction_v1/transaction_v1_header.rs +++ b/types/src/transaction/transaction_v1/transaction_v1_header.rs @@ -18,7 +18,7 @@ use crate::{ Digest, TimeDiff, Timestamp, }; #[cfg(any(feature = "std", test))] -use crate::{TransactionConfig, TransactionV1ConfigFailure, TransactionV1Hash}; +use crate::{InvalidTransactionV1, TransactionConfig, TransactionV1Hash}; /// The header portion of a [`TransactionV1`]. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] @@ -117,7 +117,7 @@ impl TransactionV1Header { timestamp_leeway: TimeDiff, at: Timestamp, transaction_hash: &TransactionV1Hash, - ) -> Result<(), TransactionV1ConfigFailure> { + ) -> Result<(), InvalidTransactionV1> { if self.ttl() > config.max_ttl { debug!( %transaction_hash, @@ -125,7 +125,7 @@ impl TransactionV1Header { max_ttl = %config.max_ttl, "transaction ttl excessive" ); - return Err(TransactionV1ConfigFailure::ExcessiveTimeToLive { + return Err(InvalidTransactionV1::ExcessiveTimeToLive { max_ttl: config.max_ttl, got: self.ttl(), }); @@ -136,7 +136,7 @@ impl TransactionV1Header { %transaction_hash, transaction_header = %self, %at, "transaction timestamp in the future" ); - return Err(TransactionV1ConfigFailure::TimestampInFuture { + return Err(InvalidTransactionV1::TimestampInFuture { validation_timestamp: at, timestamp_leeway, got: self.timestamp(), @@ -151,17 +151,20 @@ impl TransactionV1Header { self.timestamp.saturating_add(self.ttl) } - /// Returns the gas tolerance for the given transaction. - pub fn gas_tolerance(&self) -> u64 { + /// Returns the gas price tolerance for the given transaction. + pub fn gas_price_tolerance(&self) -> u8 { match self.pricing_mode { - PricingMode::Classic { gas_price, .. } => gas_price, + PricingMode::Classic { + gas_price_tolerance, + .. + } => gas_price_tolerance, PricingMode::Fixed { gas_price_tolerance, .. } => gas_price_tolerance, PricingMode::Reserved { .. } => { // TODO: Change this when reserve gets implemented. - 0u64 + 0u8 } } } @@ -173,15 +176,6 @@ impl TransactionV1Header { } impl ToBytes for TransactionV1Header { - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - self.chain_name.write_bytes(writer)?; - self.timestamp.write_bytes(writer)?; - self.ttl.write_bytes(writer)?; - self.body_hash.write_bytes(writer)?; - self.pricing_mode.write_bytes(writer)?; - self.initiator_addr.write_bytes(writer) - } - fn to_bytes(&self) -> Result, bytesrepr::Error> { let mut buffer = bytesrepr::allocate_buffer(self)?; self.write_bytes(&mut buffer)?; @@ -196,6 +190,15 @@ impl ToBytes for TransactionV1Header { + self.pricing_mode.serialized_length() + self.initiator_addr.serialized_length() } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.chain_name.write_bytes(writer)?; + self.timestamp.write_bytes(writer)?; + self.ttl.write_bytes(writer)?; + self.body_hash.write_bytes(writer)?; + self.pricing_mode.write_bytes(writer)?; + self.initiator_addr.write_bytes(writer) + } } impl FromBytes for TransactionV1Header { diff --git a/types/src/transaction/transfer_target.rs b/types/src/transaction/transfer_target.rs new file mode 100644 index 0000000000..ba38a93e3d --- /dev/null +++ b/types/src/transaction/transfer_target.rs @@ -0,0 +1,48 @@ +#[cfg(any(feature = "testing", test))] +use rand::Rng; + +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; +use crate::{account::AccountHash, PublicKey, URef}; + +/// The various types which can be used as the `target` runtime argument of a native transfer. +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum TransferTarget { + /// A public key. + PublicKey(PublicKey), + /// An account hash. + AccountHash(AccountHash), + /// A URef. + URef(URef), +} + +impl TransferTarget { + /// Returns a random `TransferTarget`. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { + match rng.gen_range(0..3) { + 0 => TransferTarget::PublicKey(PublicKey::random(rng)), + 1 => TransferTarget::AccountHash(rng.gen()), + 2 => TransferTarget::URef(rng.gen()), + _ => unreachable!(), + } + } +} + +impl From for TransferTarget { + fn from(public_key: PublicKey) -> Self { + Self::PublicKey(public_key) + } +} + +impl From for TransferTarget { + fn from(account_hash: AccountHash) -> Self { + Self::AccountHash(account_hash) + } +} + +impl From for TransferTarget { + fn from(uref: URef) -> Self { + Self::URef(uref) + } +} diff --git a/types/src/transfer.rs b/types/src/transfer.rs index 60f859aa7d..f6ae24a3ad 100644 --- a/types/src/transfer.rs +++ b/types/src/transfer.rs @@ -1,336 +1,190 @@ -use alloc::{format, string::String, vec::Vec}; -use core::{ - array::TryFromSliceError, - convert::TryFrom, - fmt::{self, Debug, Display, Formatter}, -}; +mod error; +mod transfer_v1; +mod transfer_v2; +use alloc::vec::Vec; + +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; #[cfg(feature = "datasize")] use datasize::DataSize; +#[cfg(feature = "json-schema")] +use once_cell::sync::Lazy; #[cfg(any(feature = "testing", test))] -use rand::{ - distributions::{Distribution, Standard}, - Rng, -}; +use rand::Rng; #[cfg(feature = "json-schema")] -use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema}; -use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Serializer}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; -use crate::{ - account::AccountHash, - bytesrepr::{self, FromBytes, ToBytes}, - checksummed_hex, serde_helpers, CLType, CLTyped, DeployHash, URef, U512, -}; +use crate::bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH}; +#[cfg(feature = "json-schema")] +use crate::{account::AccountHash, TransactionV1Hash, URef, U512}; +#[cfg(any(feature = "testing", feature = "json-schema", test))] +use crate::{Gas, InitiatorAddr, TransactionHash}; +pub use error::TransferFromStrError; +pub use transfer_v1::{TransferAddr, TransferV1, TRANSFER_ADDR_LENGTH}; +pub use transfer_v2::TransferV2; -/// The length of a transfer address. -pub const TRANSFER_ADDR_LENGTH: usize = 32; -pub(super) const TRANSFER_ADDR_FORMATTED_STRING_PREFIX: &str = "transfer-"; +const V1_TAG: u8 = 0; +const V2_TAG: u8 = 1; -/// Represents a transfer from one purse to another -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize, Default)] +#[cfg(feature = "json-schema")] +pub(super) static TRANSFER: Lazy = Lazy::new(|| { + let transaction_hash = TransactionHash::V1(TransactionV1Hash::from_raw([1; 32])); + let from = InitiatorAddr::AccountHash(AccountHash::new([2; 32])); + let to = Some(AccountHash::new([3; 32])); + let source = URef::from_formatted_str( + "uref-0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a-007", + ) + .unwrap(); + let target = URef::from_formatted_str( + "uref-1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b-000", + ) + .unwrap(); + let amount = U512::from(1_000_000_000_000_u64); + let gas = Gas::new(2_500_000_000_u64); + let id = Some(999); + Transfer::V2(TransferV2::new( + transaction_hash, + from, + to, + source, + target, + amount, + gas, + id, + )) +}); + +/// A versioned wrapper for a transfer. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "datasize", derive(DataSize))] #[cfg_attr(feature = "json-schema", derive(JsonSchema))] -#[serde(deny_unknown_fields)] -pub struct Transfer { - /// Deploy that created the transfer - #[serde(with = "serde_helpers::deploy_hash_as_array")] - #[cfg_attr( - feature = "json-schema", - schemars( - with = "DeployHash", - description = "Hex-encoded Deploy hash of Deploy that created the transfer." - ) - )] - pub deploy_hash: DeployHash, - /// Account from which transfer was executed - pub from: AccountHash, - /// Account to which funds are transferred - pub to: Option, - /// Source purse - pub source: URef, - /// Target purse - pub target: URef, - /// Transfer amount - pub amount: U512, - /// Gas - pub gas: U512, - /// User-defined id - pub id: Option, +pub enum Transfer { + /// A version 1 transfer. + #[serde(rename = "Version1")] + V1(TransferV1), + /// A version 2 transfer. + #[serde(rename = "Version2")] + V2(TransferV2), } impl Transfer { - /// Creates a [`Transfer`]. - #[allow(clippy::too_many_arguments)] - pub fn new( - deploy_hash: DeployHash, - from: AccountHash, - to: Option, - source: URef, - target: URef, - amount: U512, - gas: U512, - id: Option, - ) -> Self { - Transfer { - deploy_hash, - from, - to, - source, - target, - amount, - gas, - id, + // This method is not intended to be used by third party crates. + #[doc(hidden)] + #[cfg(feature = "json-schema")] + pub fn example() -> &'static Self { + &TRANSFER + } + + /// Returns a random `Transfer`. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { + use crate::DeployHash; + + if rng.gen() { + Transfer::V1(TransferV1::new( + DeployHash::random(rng), + rng.gen(), + rng.gen(), + rng.gen(), + rng.gen(), + rng.gen(), + rng.gen(), + rng.gen(), + )) + } else { + Transfer::V2(TransferV2::new( + TransactionHash::random(rng), + InitiatorAddr::random(rng), + rng.gen(), + rng.gen(), + rng.gen(), + rng.gen(), + Gas::new(rng.gen::()), + rng.gen(), + )) } } } -impl FromBytes for Transfer { - fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { - let (deploy_hash, rem) = FromBytes::from_bytes(bytes)?; - let (from, rem) = AccountHash::from_bytes(rem)?; - let (to, rem) = >::from_bytes(rem)?; - let (source, rem) = URef::from_bytes(rem)?; - let (target, rem) = URef::from_bytes(rem)?; - let (amount, rem) = U512::from_bytes(rem)?; - let (gas, rem) = U512::from_bytes(rem)?; - let (id, rem) = >::from_bytes(rem)?; - Ok(( - Transfer { - deploy_hash, - from, - to, - source, - target, - amount, - gas, - id, - }, - rem, - )) - } -} - -impl ToBytes for Transfer { - fn to_bytes(&self) -> Result, bytesrepr::Error> { - let mut result = bytesrepr::allocate_buffer(self)?; - self.deploy_hash.write_bytes(&mut result)?; - self.from.write_bytes(&mut result)?; - self.to.write_bytes(&mut result)?; - self.source.write_bytes(&mut result)?; - self.target.write_bytes(&mut result)?; - self.amount.write_bytes(&mut result)?; - self.gas.write_bytes(&mut result)?; - self.id.write_bytes(&mut result)?; - Ok(result) - } - - fn serialized_length(&self) -> usize { - self.deploy_hash.serialized_length() - + self.from.serialized_length() - + self.to.serialized_length() - + self.source.serialized_length() - + self.target.serialized_length() - + self.amount.serialized_length() - + self.gas.serialized_length() - + self.id.serialized_length() - } - - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - self.deploy_hash.write_bytes(writer)?; - self.from.write_bytes(writer)?; - self.to.write_bytes(writer)?; - self.source.write_bytes(writer)?; - self.target.write_bytes(writer)?; - self.amount.write_bytes(writer)?; - self.gas.write_bytes(writer)?; - self.id.write_bytes(writer)?; - Ok(()) - } -} - -/// Error returned when decoding a `TransferAddr` from a formatted string. -#[derive(Debug)] -#[non_exhaustive] -pub enum FromStrError { - /// The prefix is invalid. - InvalidPrefix, - /// The address is not valid hex. - Hex(base16::DecodeError), - /// The slice is the wrong length. - Length(TryFromSliceError), -} - -impl From for FromStrError { - fn from(error: base16::DecodeError) -> Self { - FromStrError::Hex(error) +impl From for Transfer { + fn from(v1_transfer: TransferV1) -> Self { + Transfer::V1(v1_transfer) } } -impl From for FromStrError { - fn from(error: TryFromSliceError) -> Self { - FromStrError::Length(error) +impl From for Transfer { + fn from(v2_transfer: TransferV2) -> Self { + Transfer::V2(v2_transfer) } } -impl Display for FromStrError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl ToBytes for Transfer { + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { match self { - FromStrError::InvalidPrefix => write!(f, "prefix is not 'transfer-'"), - FromStrError::Hex(error) => { - write!(f, "failed to decode address portion from hex: {}", error) + Transfer::V1(transfer) => { + V1_TAG.write_bytes(writer)?; + transfer.write_bytes(writer) + } + Transfer::V2(transfer) => { + V2_TAG.write_bytes(writer)?; + transfer.write_bytes(writer) } - FromStrError::Length(error) => write!(f, "address portion is wrong length: {}", error), - } - } -} - -/// A newtype wrapping a [u8; [TRANSFER_ADDR_LENGTH]] which is the raw bytes of the -/// transfer address. -#[derive(Default, PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy)] -#[cfg_attr(feature = "datasize", derive(DataSize))] -pub struct TransferAddr([u8; TRANSFER_ADDR_LENGTH]); - -impl TransferAddr { - /// Constructs a new `TransferAddr` instance from the raw bytes. - pub const fn new(value: [u8; TRANSFER_ADDR_LENGTH]) -> TransferAddr { - TransferAddr(value) - } - - /// Returns the raw bytes of the transfer address as an array. - pub fn value(&self) -> [u8; TRANSFER_ADDR_LENGTH] { - self.0 - } - - /// Returns the raw bytes of the transfer address as a `slice`. - pub fn as_bytes(&self) -> &[u8] { - &self.0 - } - - /// Formats the `TransferAddr` as a prefixed, hex-encoded string. - pub fn to_formatted_string(self) -> String { - format!( - "{}{}", - TRANSFER_ADDR_FORMATTED_STRING_PREFIX, - base16::encode_lower(&self.0), - ) - } - - /// Parses a string formatted as per `Self::to_formatted_string()` into a `TransferAddr`. - pub fn from_formatted_str(input: &str) -> Result { - let remainder = input - .strip_prefix(TRANSFER_ADDR_FORMATTED_STRING_PREFIX) - .ok_or(FromStrError::InvalidPrefix)?; - let bytes = - <[u8; TRANSFER_ADDR_LENGTH]>::try_from(checksummed_hex::decode(remainder)?.as_ref())?; - Ok(TransferAddr(bytes)) - } -} - -#[cfg(feature = "json-schema")] -impl JsonSchema for TransferAddr { - fn schema_name() -> String { - String::from("TransferAddr") - } - - fn json_schema(gen: &mut SchemaGenerator) -> Schema { - let schema = gen.subschema_for::(); - let mut schema_object = schema.into_object(); - schema_object.metadata().description = Some("Hex-encoded transfer address.".to_string()); - schema_object.into() - } -} - -impl Serialize for TransferAddr { - fn serialize(&self, serializer: S) -> Result { - if serializer.is_human_readable() { - self.to_formatted_string().serialize(serializer) - } else { - self.0.serialize(serializer) } } -} -impl<'de> Deserialize<'de> for TransferAddr { - fn deserialize>(deserializer: D) -> Result { - if deserializer.is_human_readable() { - let formatted_string = String::deserialize(deserializer)?; - TransferAddr::from_formatted_str(&formatted_string).map_err(SerdeError::custom) - } else { - let bytes = <[u8; TRANSFER_ADDR_LENGTH]>::deserialize(deserializer)?; - Ok(TransferAddr(bytes)) - } - } -} - -impl Display for TransferAddr { - fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", base16::encode_lower(&self.0)) - } -} - -impl Debug for TransferAddr { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { - write!(f, "TransferAddr({})", base16::encode_lower(&self.0)) - } -} - -impl CLTyped for TransferAddr { - fn cl_type() -> CLType { - CLType::ByteArray(TRANSFER_ADDR_LENGTH as u32) - } -} - -impl ToBytes for TransferAddr { - #[inline(always)] fn to_bytes(&self) -> Result, bytesrepr::Error> { - self.0.to_bytes() + let mut buffer = bytesrepr::allocate_buffer(self)?; + self.write_bytes(&mut buffer)?; + Ok(buffer) } - #[inline(always)] fn serialized_length(&self) -> usize { - self.0.serialized_length() - } - - #[inline(always)] - fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { - self.0.write_bytes(writer)?; - Ok(()) + U8_SERIALIZED_LENGTH + + match self { + Transfer::V1(transfer) => transfer.serialized_length(), + Transfer::V2(transfer) => transfer.serialized_length(), + } } } -impl FromBytes for TransferAddr { +impl FromBytes for Transfer { fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { - let (bytes, remainder) = FromBytes::from_bytes(bytes)?; - Ok((TransferAddr::new(bytes), remainder)) - } -} - -impl AsRef<[u8]> for TransferAddr { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -#[cfg(any(feature = "testing", test))] -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> TransferAddr { - TransferAddr::new(rng.gen()) + let (tag, remainder) = u8::from_bytes(bytes)?; + match tag { + V1_TAG => { + let (transfer, remainder) = TransferV1::from_bytes(remainder)?; + Ok((Transfer::V1(transfer), remainder)) + } + V2_TAG => { + let (transfer, remainder) = TransferV2::from_bytes(remainder)?; + Ok((Transfer::V2(transfer), remainder)) + } + _ => Err(bytesrepr::Error::Formatting), + } } } -/// Generators for [`Transfer`] +/// Proptest generators for [`Transfer`]. #[cfg(any(feature = "testing", feature = "gens", test))] pub mod gens { - use proptest::prelude::{prop::option, Arbitrary, Strategy}; + use proptest::{ + array, + prelude::{prop::option, Arbitrary, Strategy}, + }; + use super::*; use crate::{ - deploy_info::gens::{account_hash_arb, deploy_hash_arb}, - gens::{u512_arb, uref_arb}, - Transfer, + gens::{account_hash_arb, u512_arb, uref_arb}, + transaction::gens::deploy_hash_arb, }; - /// Creates an arbitrary [`Transfer`] - pub fn transfer_arb() -> impl Strategy { + pub fn transfer_v1_addr_arb() -> impl Strategy { + array::uniform32(::arbitrary()).prop_map(TransferAddr::new) + } + + pub fn transfer_v1_arb() -> impl Strategy { ( deploy_hash_arb(), account_hash_arb(), @@ -342,7 +196,7 @@ pub mod gens { option::of(::arbitrary()), ) .prop_map(|(deploy_hash, from, to, source, target, amount, gas, id)| { - Transfer { + TransferV1 { deploy_hash, from, to, @@ -358,59 +212,15 @@ pub mod gens { #[cfg(test)] mod tests { - use proptest::prelude::*; - use crate::bytesrepr; use super::*; - proptest! { - #[test] - fn test_serialization_roundtrip(transfer in gens::transfer_arb()) { - bytesrepr::test_serialization_roundtrip(&transfer) - } - } - - #[test] - fn transfer_addr_from_str() { - let transfer_address = TransferAddr([4; 32]); - let encoded = transfer_address.to_formatted_string(); - let decoded = TransferAddr::from_formatted_str(&encoded).unwrap(); - assert_eq!(transfer_address, decoded); - - let invalid_prefix = - "transfe-0000000000000000000000000000000000000000000000000000000000000000"; - assert!(TransferAddr::from_formatted_str(invalid_prefix).is_err()); - - let invalid_prefix = - "transfer0000000000000000000000000000000000000000000000000000000000000000"; - assert!(TransferAddr::from_formatted_str(invalid_prefix).is_err()); - - let short_addr = "transfer-00000000000000000000000000000000000000000000000000000000000000"; - assert!(TransferAddr::from_formatted_str(short_addr).is_err()); - - let long_addr = - "transfer-000000000000000000000000000000000000000000000000000000000000000000"; - assert!(TransferAddr::from_formatted_str(long_addr).is_err()); - - let invalid_hex = - "transfer-000000000000000000000000000000000000000000000000000000000000000g"; - assert!(TransferAddr::from_formatted_str(invalid_hex).is_err()); - } - #[test] - fn transfer_addr_serde_roundtrip() { - let transfer_address = TransferAddr([255; 32]); - let serialized = bincode::serialize(&transfer_address).unwrap(); - let decoded = bincode::deserialize(&serialized).unwrap(); - assert_eq!(transfer_address, decoded); - } + fn bytesrepr_roundtrip() { + let rng = &mut TestRng::new(); - #[test] - fn transfer_addr_json_roundtrip() { - let transfer_address = TransferAddr([255; 32]); - let json_string = serde_json::to_string_pretty(&transfer_address).unwrap(); - let decoded = serde_json::from_str(&json_string).unwrap(); - assert_eq!(transfer_address, decoded); + let transfer = Transfer::random(rng); + bytesrepr::test_serialization_roundtrip(&transfer); } } diff --git a/types/src/transfer/error.rs b/types/src/transfer/error.rs new file mode 100644 index 0000000000..b97ec03d6d --- /dev/null +++ b/types/src/transfer/error.rs @@ -0,0 +1,63 @@ +use core::{ + array::TryFromSliceError, + fmt::{self, Debug, Display, Formatter}, +}; +#[cfg(feature = "std")] +use std::error::Error as StdError; + +/// Error returned when decoding a `TransferAddr` from a formatted string. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum TransferFromStrError { + /// The prefix is invalid. + InvalidPrefix, + /// The address is not valid hex. + Hex(base16::DecodeError), + /// The slice is the wrong length. + Length(TryFromSliceError), +} + +impl From for TransferFromStrError { + fn from(error: base16::DecodeError) -> Self { + TransferFromStrError::Hex(error) + } +} + +impl From for TransferFromStrError { + fn from(error: TryFromSliceError) -> Self { + TransferFromStrError::Length(error) + } +} + +impl Display for TransferFromStrError { + fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { + match self { + TransferFromStrError::InvalidPrefix => { + write!(formatter, "transfer addr prefix is invalid",) + } + TransferFromStrError::Hex(error) => { + write!( + formatter, + "failed to decode address portion of transfer addr from hex: {}", + error + ) + } + TransferFromStrError::Length(error) => write!( + formatter, + "address portion of transfer addr is wrong length: {}", + error + ), + } + } +} + +#[cfg(feature = "std")] +impl StdError for TransferFromStrError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match self { + TransferFromStrError::InvalidPrefix => None, + TransferFromStrError::Hex(error) => Some(error), + TransferFromStrError::Length(error) => Some(error), + } + } +} diff --git a/types/src/transfer/transfer_v1.rs b/types/src/transfer/transfer_v1.rs new file mode 100644 index 0000000000..515b3c2db5 --- /dev/null +++ b/types/src/transfer/transfer_v1.rs @@ -0,0 +1,131 @@ +mod transfer_v1_addr; + +use alloc::vec::Vec; + +#[cfg(feature = "datasize")] +use datasize::DataSize; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + account::AccountHash, + bytesrepr::{self, FromBytes, ToBytes}, + serde_helpers, DeployHash, URef, U512, +}; +pub use transfer_v1_addr::{TransferAddr, TRANSFER_ADDR_LENGTH}; + +/// Represents a version 1 transfer from one purse to another. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default, Debug)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] +#[serde(deny_unknown_fields)] +pub struct TransferV1 { + /// Deploy that created the transfer + #[serde(with = "serde_helpers::deploy_hash_as_array")] + #[cfg_attr( + feature = "json-schema", + schemars( + with = "DeployHash", + description = "Hex-encoded Deploy hash of Deploy that created the transfer." + ) + )] + pub deploy_hash: DeployHash, + /// Account from which transfer was executed + pub from: AccountHash, + /// Account to which funds are transferred + pub to: Option, + /// Source purse + pub source: URef, + /// Target purse + pub target: URef, + /// Transfer amount + pub amount: U512, + /// Gas + pub gas: U512, + /// User-defined id + pub id: Option, +} + +impl TransferV1 { + /// Creates a [`TransferV1`]. + #[allow(clippy::too_many_arguments)] + pub fn new( + deploy_hash: DeployHash, + from: AccountHash, + to: Option, + source: URef, + target: URef, + amount: U512, + gas: U512, + id: Option, + ) -> Self { + TransferV1 { + deploy_hash, + from, + to, + source, + target, + amount, + gas, + id, + } + } +} + +impl ToBytes for TransferV1 { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buffer = bytesrepr::allocate_buffer(self)?; + self.write_bytes(&mut buffer)?; + Ok(buffer) + } + + fn serialized_length(&self) -> usize { + self.deploy_hash.serialized_length() + + self.from.serialized_length() + + self.to.serialized_length() + + self.source.serialized_length() + + self.target.serialized_length() + + self.amount.serialized_length() + + self.gas.serialized_length() + + self.id.serialized_length() + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.deploy_hash.write_bytes(writer)?; + self.from.write_bytes(writer)?; + self.to.write_bytes(writer)?; + self.source.write_bytes(writer)?; + self.target.write_bytes(writer)?; + self.amount.write_bytes(writer)?; + self.gas.write_bytes(writer)?; + self.id.write_bytes(writer)?; + Ok(()) + } +} + +impl FromBytes for TransferV1 { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (deploy_hash, rem) = FromBytes::from_bytes(bytes)?; + let (from, rem) = AccountHash::from_bytes(rem)?; + let (to, rem) = >::from_bytes(rem)?; + let (source, rem) = URef::from_bytes(rem)?; + let (target, rem) = URef::from_bytes(rem)?; + let (amount, rem) = U512::from_bytes(rem)?; + let (gas, rem) = U512::from_bytes(rem)?; + let (id, rem) = >::from_bytes(rem)?; + Ok(( + TransferV1 { + deploy_hash, + from, + to, + source, + target, + amount, + gas, + id, + }, + rem, + )) + } +} diff --git a/types/src/transfer/transfer_v1/transfer_v1_addr.rs b/types/src/transfer/transfer_v1/transfer_v1_addr.rs new file mode 100644 index 0000000000..42381ac05e --- /dev/null +++ b/types/src/transfer/transfer_v1/transfer_v1_addr.rs @@ -0,0 +1,219 @@ +use alloc::{format, string::String, vec::Vec}; +use core::{ + convert::TryFrom, + fmt::{self, Debug, Display, Formatter}, +}; + +#[cfg(feature = "datasize")] +use datasize::DataSize; +#[cfg(any(feature = "testing", test))] +use rand::Rng; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; +use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Serializer}; + +use super::super::TransferFromStrError; +pub(super) const TRANSFER_ADDR_FORMATTED_STRING_PREFIX: &str = "transfer-"; +#[cfg(any(feature = "testing", test))] +use crate::testing::TestRng; +use crate::{ + bytesrepr::{self, FromBytes, ToBytes}, + checksummed_hex, CLType, CLTyped, +}; + +/// The length of a version 1 transfer address. +pub const TRANSFER_ADDR_LENGTH: usize = 32; + +/// A newtype wrapping a [u8; [TRANSFER_ADDR_LENGTH]] which is the raw bytes of the +/// transfer address. +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr( + feature = "json-schema", + derive(JsonSchema), + schemars(description = "Hex-encoded version 1 transfer address.") +)] +pub struct TransferAddr( + #[cfg_attr(feature = "json-schema", schemars(skip, with = "String"))] + [u8; TRANSFER_ADDR_LENGTH], +); + +impl TransferAddr { + /// Constructs a new `TransferV1Addr` instance from the raw bytes. + pub const fn new(value: [u8; TRANSFER_ADDR_LENGTH]) -> TransferAddr { + TransferAddr(value) + } + + /// Returns the raw bytes of the transfer address as an array. + pub fn value(&self) -> [u8; TRANSFER_ADDR_LENGTH] { + self.0 + } + + /// Returns the raw bytes of the transfer address as a `slice`. + pub fn as_bytes(&self) -> &[u8] { + &self.0 + } + + /// Formats the `TransferV1Addr` as a prefixed, hex-encoded string. + pub fn to_formatted_string(self) -> String { + format!( + "{}{}", + TRANSFER_ADDR_FORMATTED_STRING_PREFIX, + base16::encode_lower(&self.0), + ) + } + + /// Parses a string formatted as per `Self::to_formatted_string()` into a `TransferV1Addr`. + pub fn from_formatted_str(input: &str) -> Result { + let remainder = input + .strip_prefix(TRANSFER_ADDR_FORMATTED_STRING_PREFIX) + .ok_or(TransferFromStrError::InvalidPrefix)?; + let bytes = + <[u8; TRANSFER_ADDR_LENGTH]>::try_from(checksummed_hex::decode(remainder)?.as_ref())?; + Ok(TransferAddr(bytes)) + } + + /// Returns a random `TransferV1Addr`. + #[cfg(any(feature = "testing", test))] + pub fn random(rng: &mut TestRng) -> Self { + TransferAddr(rng.gen()) + } +} + +impl Serialize for TransferAddr { + fn serialize(&self, serializer: S) -> Result { + if serializer.is_human_readable() { + self.to_formatted_string().serialize(serializer) + } else { + self.0.serialize(serializer) + } + } +} + +impl<'de> Deserialize<'de> for TransferAddr { + fn deserialize>(deserializer: D) -> Result { + if deserializer.is_human_readable() { + let formatted_string = String::deserialize(deserializer)?; + TransferAddr::from_formatted_str(&formatted_string).map_err(SerdeError::custom) + } else { + let bytes = <[u8; TRANSFER_ADDR_LENGTH]>::deserialize(deserializer)?; + Ok(TransferAddr(bytes)) + } + } +} + +impl Display for TransferAddr { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + write!(formatter, "{}", base16::encode_lower(&self.0)) + } +} + +impl Debug for TransferAddr { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "TransferV1Addr({})", base16::encode_lower(&self.0)) + } +} + +impl CLTyped for TransferAddr { + fn cl_type() -> CLType { + CLType::ByteArray(TRANSFER_ADDR_LENGTH as u32) + } +} + +impl ToBytes for TransferAddr { + #[inline(always)] + fn to_bytes(&self) -> Result, bytesrepr::Error> { + self.0.to_bytes() + } + + #[inline(always)] + fn serialized_length(&self) -> usize { + self.0.serialized_length() + } + + #[inline(always)] + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.0.write_bytes(writer) + } +} + +impl FromBytes for TransferAddr { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (bytes, remainder) = <[u8; TRANSFER_ADDR_LENGTH]>::from_bytes(bytes)?; + Ok((TransferAddr(bytes), remainder)) + } +} + +#[cfg(test)] +mod tests { + use crate::{bytesrepr, testing::TestRng}; + + use super::*; + + #[test] + fn transfer_addr_from_str() { + let transfer_address = TransferAddr([4; 32]); + let encoded = transfer_address.to_formatted_string(); + let decoded = TransferAddr::from_formatted_str(&encoded).unwrap(); + assert_eq!(transfer_address, decoded); + + let invalid_prefix = + "transferv-0000000000000000000000000000000000000000000000000000000000000000"; + assert!(matches!( + TransferAddr::from_formatted_str(invalid_prefix), + Err(TransferFromStrError::InvalidPrefix) + )); + + let invalid_prefix = + "transfer0000000000000000000000000000000000000000000000000000000000000000"; + assert!(matches!( + TransferAddr::from_formatted_str(invalid_prefix), + Err(TransferFromStrError::InvalidPrefix) + )); + + let short_addr = "transfer-00000000000000000000000000000000000000000000000000000000000000"; + assert!(matches!( + TransferAddr::from_formatted_str(short_addr), + Err(TransferFromStrError::Length(_)) + )); + + let long_addr = + "transfer-000000000000000000000000000000000000000000000000000000000000000000"; + assert!(matches!( + TransferAddr::from_formatted_str(long_addr), + Err(TransferFromStrError::Length(_)) + )); + + let invalid_hex = + "transfer-000000000000000000000000000000000000000000000000000000000000000g"; + assert!(matches!( + TransferAddr::from_formatted_str(invalid_hex), + Err(TransferFromStrError::Hex(_)) + )); + } + + #[test] + fn bytesrepr_roundtrip() { + let rng = &mut TestRng::new(); + let transfer_address = TransferAddr::random(rng); + bytesrepr::test_serialization_roundtrip(&transfer_address) + } + + #[test] + fn bincode_roundtrip() { + let rng = &mut TestRng::new(); + let transfer_address = TransferAddr::random(rng); + let serialized = bincode::serialize(&transfer_address).unwrap(); + let decoded = bincode::deserialize(&serialized).unwrap(); + assert_eq!(transfer_address, decoded); + } + + #[test] + fn json_roundtrip() { + let rng = &mut TestRng::new(); + let transfer_address = TransferAddr::random(rng); + let json_string = serde_json::to_string_pretty(&transfer_address).unwrap(); + let decoded = serde_json::from_str(&json_string).unwrap(); + assert_eq!(transfer_address, decoded); + } +} diff --git a/types/src/transfer/transfer_v2.rs b/types/src/transfer/transfer_v2.rs new file mode 100644 index 0000000000..c3ff440f8f --- /dev/null +++ b/types/src/transfer/transfer_v2.rs @@ -0,0 +1,119 @@ +use alloc::vec::Vec; + +#[cfg(feature = "datasize")] +use datasize::DataSize; +#[cfg(feature = "json-schema")] +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + account::AccountHash, + bytesrepr::{self, FromBytes, ToBytes}, + Gas, InitiatorAddr, TransactionHash, URef, U512, +}; + +/// Represents a version 2 transfer from one purse to another. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "datasize", derive(DataSize))] +#[cfg_attr(feature = "json-schema", derive(JsonSchema))] +#[serde(deny_unknown_fields)] +pub struct TransferV2 { + /// Transaction that created the transfer. + pub transaction_hash: TransactionHash, + /// Entity from which transfer was executed. + pub from: InitiatorAddr, + /// Account to which funds are transferred. + pub to: Option, + /// Source purse. + pub source: URef, + /// Target purse. + pub target: URef, + /// Transfer amount. + pub amount: U512, + /// Gas. + pub gas: Gas, + /// User-defined ID. + pub id: Option, +} + +impl TransferV2 { + /// Creates a [`TransferV2`]. + #[allow(clippy::too_many_arguments)] + pub fn new( + transaction_hash: TransactionHash, + from: InitiatorAddr, + to: Option, + source: URef, + target: URef, + amount: U512, + gas: Gas, + id: Option, + ) -> Self { + TransferV2 { + transaction_hash, + from, + to, + source, + target, + amount, + gas, + id, + } + } +} + +impl ToBytes for TransferV2 { + fn to_bytes(&self) -> Result, bytesrepr::Error> { + let mut buf = Vec::new(); + self.write_bytes(&mut buf)?; + Ok(buf) + } + + fn serialized_length(&self) -> usize { + self.transaction_hash.serialized_length() + + self.from.serialized_length() + + self.to.serialized_length() + + self.source.serialized_length() + + self.target.serialized_length() + + self.amount.serialized_length() + + self.gas.serialized_length() + + self.id.serialized_length() + } + + fn write_bytes(&self, writer: &mut Vec) -> Result<(), bytesrepr::Error> { + self.transaction_hash.write_bytes(writer)?; + self.from.write_bytes(writer)?; + self.to.write_bytes(writer)?; + self.source.write_bytes(writer)?; + self.target.write_bytes(writer)?; + self.amount.write_bytes(writer)?; + self.gas.write_bytes(writer)?; + self.id.write_bytes(writer) + } +} + +impl FromBytes for TransferV2 { + fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> { + let (transaction_hash, remainder) = TransactionHash::from_bytes(bytes)?; + let (from, remainder) = InitiatorAddr::from_bytes(remainder)?; + let (to, remainder) = >::from_bytes(remainder)?; + let (source, remainder) = URef::from_bytes(remainder)?; + let (target, remainder) = URef::from_bytes(remainder)?; + let (amount, remainder) = U512::from_bytes(remainder)?; + let (gas, remainder) = Gas::from_bytes(remainder)?; + let (id, remainder) = >::from_bytes(remainder)?; + Ok(( + TransferV2 { + transaction_hash, + from, + to, + source, + target, + amount, + gas, + id, + }, + remainder, + )) + } +} diff --git a/utils/global-state-update-gen/src/admins.rs b/utils/global-state-update-gen/src/admins.rs index 23b5e0c4e0..4a6e08f802 100644 --- a/utils/global-state-update-gen/src/admins.rs +++ b/utils/global-state-update-gen/src/admins.rs @@ -1,4 +1,5 @@ use casper_engine_test_support::LmdbWasmTestBuilder; +use casper_execution_engine::engine_state::engine_config::DEFAULT_PROTOCOL_VERSION; use casper_types::{ account::Account, addressable_entity::NamedKeys, bytesrepr::ToBytes, system::mint, AccessRights, AsymmetricType, CLTyped, CLValue, Key, PublicKey, StoredValue, URef, U512, @@ -25,11 +26,16 @@ pub(crate) fn generate_admins(matches: &ArgMatches<'_>) { // Open the global state that should be in the supplied directory. let post_state_hash = hash_from_str(state_hash); - let test_builder = LmdbWasmTestBuilder::open_raw(data_dir, Default::default(), post_state_hash); + let test_builder = LmdbWasmTestBuilder::open_raw( + data_dir, + Default::default(), + DEFAULT_PROTOCOL_VERSION, + post_state_hash, + ); let admin_values = matches.values_of("admin").expect("at least one argument"); - - let mut total_supply = test_builder.total_supply(Some(post_state_hash)); + let protocol_version = DEFAULT_PROTOCOL_VERSION; + let mut total_supply = test_builder.total_supply(Some(post_state_hash), protocol_version); let total_supply_before = total_supply; for value in admin_values { diff --git a/utils/global-state-update-gen/src/balances.rs b/utils/global-state-update-gen/src/balances.rs index dfc8450c39..e9a7a5d4a4 100644 --- a/utils/global-state-update-gen/src/balances.rs +++ b/utils/global-state-update-gen/src/balances.rs @@ -1,6 +1,7 @@ use clap::ArgMatches; use casper_engine_test_support::LmdbWasmTestBuilder; +use casper_execution_engine::engine_state::engine_config::DEFAULT_PROTOCOL_VERSION; use casper_types::{account::AccountHash, U512}; use crate::{ @@ -33,6 +34,11 @@ pub(crate) fn generate_balances_update(matches: &ArgMatches<'_>) { protocol_version, }; - let builder = LmdbWasmTestBuilder::open_raw(data_dir, Default::default(), state_hash); + let builder = LmdbWasmTestBuilder::open_raw( + data_dir, + Default::default(), + DEFAULT_PROTOCOL_VERSION, + state_hash, + ); update_from_config(builder, config); } diff --git a/utils/global-state-update-gen/src/generic.rs b/utils/global-state-update-gen/src/generic.rs index cbb6d81a26..075d4bba46 100644 --- a/utils/global-state-update-gen/src/generic.rs +++ b/utils/global-state-update-gen/src/generic.rs @@ -14,6 +14,7 @@ use clap::ArgMatches; use itertools::Itertools; use casper_engine_test_support::LmdbWasmTestBuilder; +use casper_execution_engine::engine_state::engine_config::DEFAULT_PROTOCOL_VERSION; use casper_types::{ system::auction::{ Bid, BidKind, BidsExt, Delegator, SeigniorageRecipient, SeigniorageRecipientsSnapshot, @@ -39,7 +40,12 @@ pub(crate) fn generate_generic_update(matches: &ArgMatches<'_>) { let config_bytes = fs::read(config_path).expect("couldn't read the config file"); let config: Config = toml::from_slice(&config_bytes).expect("couldn't parse the config file"); - let builder = LmdbWasmTestBuilder::open_raw(data_dir, Default::default(), state_hash); + let builder = LmdbWasmTestBuilder::open_raw( + data_dir, + Default::default(), + DEFAULT_PROTOCOL_VERSION, + state_hash, + ); update_from_config(builder, config); } diff --git a/utils/global-state-update-gen/src/generic/state_tracker.rs b/utils/global-state-update-gen/src/generic/state_tracker.rs index f06588bd99..01fc677870 100644 --- a/utils/global-state-update-gen/src/generic/state_tracker.rs +++ b/utils/global-state-update-gen/src/generic/state_tracker.rs @@ -9,10 +9,10 @@ use rand::Rng; use casper_types::{ account::AccountHash, addressable_entity::{ActionThresholds, AssociatedKeys, MessageTopics, Weight}, - package::{EntityVersions, Groups, PackageStatus}, system::auction::{BidAddr, BidKind, BidsExt, SeigniorageRecipientsSnapshot, UnbondingPurse}, AccessRights, AddressableEntity, AddressableEntityHash, ByteCodeHash, CLValue, EntityKind, - EntryPoints, Key, Package, PackageHash, ProtocolVersion, PublicKey, StoredValue, URef, U512, + EntityVersions, EntryPoints, Groups, Key, Package, PackageHash, PackageStatus, ProtocolVersion, + PublicKey, StoredValue, URef, U512, }; use super::{config::Transfer, state_reader::StateReader}; diff --git a/utils/global-state-update-gen/src/main.rs b/utils/global-state-update-gen/src/main.rs index cb651851cb..85e150b72f 100644 --- a/utils/global-state-update-gen/src/main.rs +++ b/utils/global-state-update-gen/src/main.rs @@ -1,7 +1,7 @@ mod admins; mod balances; mod generic; -mod system_contract_registry; +mod system_entity_registry; mod utils; mod validators; @@ -10,7 +10,7 @@ use clap::{crate_version, App, Arg, SubCommand}; use crate::{ balances::generate_balances_update, generic::generate_generic_update, - system_contract_registry::generate_system_contract_registry, + system_entity_registry::generate_system_entity_registry, validators::generate_validators_update, }; @@ -102,7 +102,7 @@ fn main() { ) .subcommand( SubCommand::with_name("migrate-into-system-contract-registry") - .about("Generates an update creating the system contract registry") + .about("Generates an update creating the system entity registry") .arg( Arg::with_name("data_dir") .short("d") @@ -190,7 +190,7 @@ fn main() { ("change-validators", Some(sub_matches)) => generate_validators_update(sub_matches), ("balances", Some(sub_matches)) => generate_balances_update(sub_matches), ("migrate-into-system-contract-registry", Some(sub_matches)) => { - generate_system_contract_registry(sub_matches) + generate_system_entity_registry(sub_matches) } ("generic", Some(sub_matches)) => generate_generic_update(sub_matches), ("generate-admins", Some(sub_matches)) => generate_admins(sub_matches), diff --git a/utils/global-state-update-gen/src/system_contract_registry.rs b/utils/global-state-update-gen/src/system_entity_registry.rs similarity index 87% rename from utils/global-state-update-gen/src/system_contract_registry.rs rename to utils/global-state-update-gen/src/system_entity_registry.rs index b768fc51e9..12c0723280 100644 --- a/utils/global-state-update-gen/src/system_contract_registry.rs +++ b/utils/global-state-update-gen/src/system_entity_registry.rs @@ -4,6 +4,7 @@ use clap::ArgMatches; use lmdb::{self, Cursor, Environment, EnvironmentFlags, Transaction}; use casper_engine_test_support::LmdbWasmTestBuilder; +use casper_execution_engine::engine_state::engine_config::DEFAULT_PROTOCOL_VERSION; use casper_storage::{ data_access_layer::{ SystemEntityRegistryPayload, SystemEntityRegistryRequest, SystemEntityRegistrySelector, @@ -21,15 +22,15 @@ use crate::utils::{hash_from_str, print_entry}; const DATABASE_NAME: &str = "PROTOCOL_DATA_STORE"; -pub(crate) fn generate_system_contract_registry(matches: &ArgMatches<'_>) { +pub(crate) fn generate_system_entity_registry(matches: &ArgMatches<'_>) { let data_dir = Path::new(matches.value_of("data_dir").unwrap_or(".")); match matches.value_of("hash") { - None => generate_system_contract_registry_using_protocol_data(data_dir), - Some(hash) => generate_system_contract_registry_using_global_state(data_dir, hash), + None => generate_system_entity_registry_using_protocol_data(data_dir), + Some(hash) => generate_system_entity_registry_using_global_state(data_dir, hash), } } -fn generate_system_contract_registry_using_protocol_data(data_dir: &Path) { +fn generate_system_entity_registry_using_protocol_data(data_dir: &Path) { let database_path = data_dir.join("data.lmdb"); let env = Environment::new() @@ -110,9 +111,13 @@ fn generate_system_contract_registry_using_protocol_data(data_dir: &Path) { ); } -fn generate_system_contract_registry_using_global_state(data_dir: &Path, state_hash: &str) { - let builder = - LmdbWasmTestBuilder::open_raw(data_dir, Default::default(), hash_from_str(state_hash)); +fn generate_system_entity_registry_using_global_state(data_dir: &Path, state_hash: &str) { + let builder = LmdbWasmTestBuilder::open_raw( + data_dir, + Default::default(), + DEFAULT_PROTOCOL_VERSION, + hash_from_str(state_hash), + ); let registry_req = SystemEntityRegistryRequest::new( builder.get_post_state_hash(), diff --git a/utils/global-state-update-gen/src/validators.rs b/utils/global-state-update-gen/src/validators.rs index 8517d4f281..b3db70d084 100644 --- a/utils/global-state-update-gen/src/validators.rs +++ b/utils/global-state-update-gen/src/validators.rs @@ -1,4 +1,5 @@ use casper_engine_test_support::LmdbWasmTestBuilder; +use casper_execution_engine::engine_state::engine_config::DEFAULT_PROTOCOL_VERSION; use casper_types::{AsymmetricType, PublicKey, U512}; use clap::ArgMatches; @@ -59,6 +60,11 @@ pub(crate) fn generate_validators_update(matches: &ArgMatches<'_>) { protocol_version, }; - let builder = LmdbWasmTestBuilder::open_raw(data_dir, Default::default(), state_hash); + let builder = LmdbWasmTestBuilder::open_raw( + data_dir, + Default::default(), + DEFAULT_PROTOCOL_VERSION, + state_hash, + ); update_from_config(builder, config); } diff --git a/utils/validation/src/generators.rs b/utils/validation/src/generators.rs index a1c33ebf8e..5f4cbcc888 100644 --- a/utils/validation/src/generators.rs +++ b/utils/validation/src/generators.rs @@ -11,15 +11,18 @@ use casper_types::{ addressable_entity::{ ActionThresholds, AddressableEntity, AssociatedKeys, EntityKind, MessageTopics, NamedKeys, }, - package::{EntityVersions, Groups, Package, PackageStatus}, - system::auction::{ - Bid, BidAddr, BidKind, Delegator, EraInfo, SeigniorageAllocation, UnbondingPurse, - ValidatorBid, WithdrawPurse, + system::{ + auction::{ + Bid, BidAddr, BidKind, Delegator, EraInfo, SeigniorageAllocation, UnbondingPurse, + ValidatorBid, WithdrawPurse, + }, + mint::BalanceHoldAddr, }, - AccessRights, AddressableEntityHash, ByteCode, ByteCodeHash, ByteCodeKind, CLType, CLTyped, - CLValue, DeployHash, DeployInfo, EntityVersionKey, EntryPoint, EntryPointAccess, - EntryPointType, EntryPoints, EraId, Group, Key, PackageHash, Parameter, ProtocolVersion, - PublicKey, SecretKey, StoredValue, Transfer, TransferAddr, URef, U512, + AccessRights, AddressableEntityHash, BlockTime, ByteCode, ByteCodeHash, ByteCodeKind, CLType, + CLTyped, CLValue, DeployHash, DeployInfo, EntityVersionKey, EntityVersions, EntryPoint, + EntryPointAccess, EntryPointType, EntryPoints, EraId, Group, Groups, Key, Package, PackageHash, + PackageStatus, Parameter, ProtocolVersion, PublicKey, SecretKey, StoredValue, TransferAddr, + TransferV1, URef, U512, }; use casper_validation::{ abi::{ABIFixture, ABITestCase}, @@ -66,7 +69,7 @@ pub fn make_abi_test_fixtures() -> Result { } }; - let transfer = Transfer::new( + let legacy_transfer = TransferV1::new( DeployHash::from_raw([44; 32]), AccountHash::new([100; 32]), Some(AccountHash::new([101; 32])), @@ -206,9 +209,13 @@ pub fn make_abi_test_fixtures() -> Result { const DEPLOY_INFO_KEY: Key = Key::DeployInfo(DeployHash::from_raw([42; 32])); const ERA_INFO_KEY: Key = Key::EraInfo(EraId::new(42)); const BALANCE_KEY: Key = Key::Balance([42; 32]); + const BALANCE_HOLD_KEY: Key = Key::BalanceHold(BalanceHoldAddr::Gas { + purse_addr: [42; 32], + block_time: BlockTime::new(0), + }); const WITHDRAW_KEY: Key = Key::Withdraw(AccountHash::new([42; 32])); const DICTIONARY_KEY: Key = Key::Dictionary([42; 32]); - const SYSTEM_CONTRACT_REGISTRY_KEY: Key = Key::SystemEntityRegistry; + const SYSTEM_ENTITY_REGISTRY_KEY: Key = Key::SystemEntityRegistry; const ERA_SUMMARY_KEY: Key = Key::EraSummary; const UNBOND_KEY: Key = Key::Unbond(AccountHash::new([42; 32])); const CHAINSPEC_REGISTRY_KEY: Key = Key::ChainspecRegistry; @@ -228,7 +235,7 @@ pub fn make_abi_test_fixtures() -> Result { ABITestCase::from_inputs(vec![UREF_KEY.into()])?, ); keys.insert( - "Transfer".to_string(), + "LegacyTransfer".to_string(), ABITestCase::from_inputs(vec![TRANSFER_KEY.into()])?, ); keys.insert( @@ -243,6 +250,10 @@ pub fn make_abi_test_fixtures() -> Result { "Balance".to_string(), ABITestCase::from_inputs(vec![BALANCE_KEY.into()])?, ); + keys.insert( + "BalanceHold".to_string(), + ABITestCase::from_inputs(vec![BALANCE_HOLD_KEY.into()])?, + ); keys.insert( "WriteBid".to_string(), ABITestCase::from_inputs(vec![original_bid_key.into()])?, @@ -269,8 +280,8 @@ pub fn make_abi_test_fixtures() -> Result { ABITestCase::from_inputs(vec![DICTIONARY_KEY.into()])?, ); keys.insert( - "SystemContractRegistry".to_string(), - ABITestCase::from_inputs(vec![SYSTEM_CONTRACT_REGISTRY_KEY.into()])?, + "SystemEntityRegistry".to_string(), + ABITestCase::from_inputs(vec![SYSTEM_ENTITY_REGISTRY_KEY.into()])?, ); keys.insert( "EraSummary".to_string(), @@ -351,7 +362,7 @@ pub fn make_abi_test_fixtures() -> Result { ], CLType::Unit, EntryPointAccess::Public, - EntryPointType::AddressableEntity, + EntryPointType::Called, ); entry_points.add_entry_point(public_contract_entry_point); @@ -407,8 +418,8 @@ pub fn make_abi_test_fixtures() -> Result { ); stored_value.insert( - "Transfer".to_string(), - ABITestCase::from_inputs(vec![StoredValue::Transfer(transfer).into()])?, + "LegacyTransfer".to_string(), + ABITestCase::from_inputs(vec![StoredValue::LegacyTransfer(legacy_transfer).into()])?, ); stored_value.insert( "DeployInfo".to_string(), diff --git a/utils/validation/tests/fixtures/ABI/key.json b/utils/validation/tests/fixtures/ABI/key.json index 6315c07f33..ee52ae10d4 100644 --- a/utils/validation/tests/fixtures/ABI/key.json +++ b/utils/validation/tests/fixtures/ABI/key.json @@ -17,6 +17,15 @@ ], "output": "062a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" }, + "BalanceHold": { + "input": [ + { + "type": "Key", + "value": "balance-hold-002a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0000000000000000" + } + ], + "output": "16002a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0000000000000000" + }, "ChainspecRegistry": { "input": [ { @@ -80,23 +89,23 @@ ], "output": "012a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" }, - "SystemContractRegistry": { + "LegacyTransfer": { "input": [ { "type": "Key", - "value": "system-contract-registry-0000000000000000000000000000000000000000000000000000000000000000" + "value": "transfer-2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" } ], - "output": "0a0000000000000000000000000000000000000000000000000000000000000000" + "output": "032a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" }, - "Transfer": { + "SystemEntityRegistry": { "input": [ { "type": "Key", - "value": "transfer-2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + "value": "system-entity-registry-0000000000000000000000000000000000000000000000000000000000000000" } ], - "output": "032a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + "output": "0a0000000000000000000000000000000000000000000000000000000000000000" }, "URef": { "input": [ @@ -150,7 +159,7 @@ "value": "bid-addr-00306633f962155a7d46658adb36143f28668f530454fe788c927cecf62e5964a1" } ], - "output": "0f306633f962155a7d46658adb36143f28668f530454fe788c927cecf62e5964a1" + "output": "0f00306633f962155a7d46658adb36143f28668f530454fe788c927cecf62e5964a1" }, "WriteValidatorBid": { "input": [ diff --git a/utils/validation/tests/fixtures/ABI/stored_value.json b/utils/validation/tests/fixtures/ABI/stored_value.json index 3e50ac4403..8aedc86b66 100644 --- a/utils/validation/tests/fixtures/ABI/stored_value.json +++ b/utils/validation/tests/fixtures/ABI/stored_value.json @@ -39,8 +39,11 @@ "type": "StoredValue", "value": { "AddressableEntity": { + "protocol_version": "1.0.0", + "entity_kind": "SmartContract", "package_hash": "contract-package-6464646464646464646464646464646464646464646464646464646464646464", "byte_code_hash": "byte-code-6565656565656565656565656565656565656565656565656565656565656565", + "main_purse": "uref-0000000000000000000000000000000000000000000000000000000000000000-000", "entry_points": [ { "name": "public_entry_point_func", @@ -58,20 +61,17 @@ ], "ret": "Unit", "access": "Public", - "entry_point_type": "AddressableEntity" + "entry_point_type": "Called" } } ], - "protocol_version": "1.0.0", - "main_purse": "uref-0000000000000000000000000000000000000000000000000000000000000000-000", "associated_keys": [], "action_thresholds": { "deployment": 1, "upgrade_management": 1, "key_management": 1 }, - "message_topics": [], - "entity_kind": "SmartContract" + "message_topics": [] } } } @@ -212,6 +212,26 @@ ], "output": "07020000000001197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d610400ca9a3b010202bb58b5feca505c74edc000d8282fc556e51a1024fc8e7d7e56c6f887c5c8d5f201197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d610400ca9a3b" }, + "LegacyTransfer": { + "input": [ + { + "type": "StoredValue", + "value": { + "LegacyTransfer": { + "deploy_hash": "2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c", + "from": "account-hash-6464646464646464646464646464646464646464646464646464646464646464", + "to": "account-hash-6565656565656565656565656565656565656565656565656565656565656565", + "source": "uref-0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a-002", + "target": "uref-0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b-002", + "amount": "15000000000", + "gas": "2500000000", + "id": 1 + } + } + } + ], + "output": "052c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c64646464646464646464646464646464646464646464646464646464646464640165656565656565656565656565656565656565656565656565656565656565650a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a020b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b020500d6117e030400f90295010100000000000000" + }, "Package": { "input": [ { @@ -260,26 +280,6 @@ ], "output": "0c2727272727272727272727272727272727272727272727272727272727272727010200000001000000010000006464646464646464646464646464646464646464646464646464646464646464010000000200000063636363636363636363636363636363636363636363636363636363636363630100000001000000010000000200000005000000456d707479000000000600000053696e676c650100000037373737373737373737373737373737373737373737373737373737373737370101" }, - "Transfer": { - "input": [ - { - "type": "StoredValue", - "value": { - "Transfer": { - "deploy_hash": "2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c", - "from": "account-hash-6464646464646464646464646464646464646464646464646464646464646464", - "to": "account-hash-6565656565656565656565656565656565656565656565656565656565656565", - "source": "uref-0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a-002", - "target": "uref-0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b-002", - "amount": "15000000000", - "gas": "2500000000", - "id": 1 - } - } - } - ], - "output": "052c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c64646464646464646464646464646464646464646464646464646464646464640165656565656565656565656565656565656565656565656565656565656565650a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a020b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b020500d6117e030400f90295010100000000000000" - }, "Unbonding": { "input": [ {