diff --git a/Cargo.lock b/Cargo.lock index de4d3e986333..24194458ad6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,6 +264,7 @@ name = "actor" version = "0.1.0" dependencies = [ "ahash 0.4.4", + "base64 0.12.3", "bitfield", "byteorder 1.3.4", "clock", diff --git a/blockchain/chain_sync/src/sync.rs b/blockchain/chain_sync/src/sync.rs index be5fb1522574..30ffcaeee4f6 100644 --- a/blockchain/chain_sync/src/sync.rs +++ b/blockchain/chain_sync/src/sync.rs @@ -1096,7 +1096,7 @@ mod tests { let (bls, secp) = construct_messages(); let expected_root = - Cid::from_raw_cid("bafy2bzacecujyfvb74s7xxnlajidxpgcpk6abyatk62dlhgq6gcob3iixhgom") + Cid::from_raw_cid("bafy2bzacebx7t56l6urh4os4kzar5asc5hmbhl7so6sfkzcgpjforkwylmqxa") .unwrap(); let root = compute_msg_meta(cs.chain_store.blockstore(), &[bls], &[secp]).unwrap(); diff --git a/vm/actor/Cargo.toml b/vm/actor/Cargo.toml index ad8d42f512f5..65159f0b8e7e 100644 --- a/vm/actor/Cargo.toml +++ b/vm/actor/Cargo.toml @@ -29,6 +29,7 @@ fil_types = { path = "../../types" } derive_builder = "0.9" byteorder = "1.3.4" ahash = "0.4" +base64 = "0.12.1" [dev-dependencies] db = { path = "../../node/db" } diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index fe136ff77dfc..28959e1f0937 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -10,7 +10,9 @@ use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; -use vm::{ActorError, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; +use vm::{actor_error, ActorError, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; + +// * Updated to specs-actors commit: 4784ddb8e54d53c118e63763e4efbcf0a419da28 /// Account actor methods available #[derive(FromPrimitive)] @@ -33,10 +35,8 @@ impl Actor { match address.protocol() { Protocol::Secp256k1 | Protocol::BLS => {} protocol => { - return Err(rt.abort( - ExitCode::ErrIllegalArgument, - format!("address must use BLS or SECP protocol, got {}", protocol), - )); + return Err(actor_error!(ErrIllegalArgument; + "address must use BLS or SECP protocol, got {}", protocol)); } } rt.create(&State { address })?; @@ -74,9 +74,9 @@ impl ActorCode for Actor { Some(Method::PubkeyAddress) => { check_empty_params(params)?; let addr = Self::pubkey_address(rt)?; - Ok(Serialized::serialize(addr).unwrap()) + Ok(Serialized::serialize(addr)?) } - _ => Err(rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method")), + None => Err(actor_error!(SysErrInvalidMethod; "Invalid method")), } } } diff --git a/vm/actor/src/lib.rs b/vm/actor/src/lib.rs index 55e84cd949b4..9b471075bd83 100644 --- a/vm/actor/src/lib.rs +++ b/vm/actor/src/lib.rs @@ -12,10 +12,9 @@ mod util; pub use self::builtin::*; pub use self::util::*; -pub use vm::{ActorState, DealID, Serialized}; +pub use vm::{actor_error, ActorError, ActorState, DealID, ExitCode, Serialized}; use cid::Cid; -use encoding::Error as EncodingError; use ipld_blockstore::BlockStore; use ipld_hamt::{BytesKey, Error as HamtError, Hamt}; use num_bigint::BigUint; @@ -23,16 +22,17 @@ use unsigned_varint::decode::Error as UVarintError; const HAMT_BIT_WIDTH: u8 = 5; -type EmptyType = [u8; 0]; -const EMPTY_VALUE: EmptyType = []; - /// Deal weight type DealWeight = BigUint; /// Used when invocation requires parameters to be an empty array of bytes -#[inline] -fn check_empty_params(params: &Serialized) -> Result<(), EncodingError> { - params.deserialize::<[u8; 0]>().map(|_| ()) +fn check_empty_params(params: &Serialized) -> Result<(), ActorError> { + if !params.is_empty() { + Err(actor_error!(ErrSerialization; + "params expected to be empty, was: {}", base64::encode(params.bytes()))) + } else { + Ok(()) + } } /// Create a hamt configured with constant bit width. diff --git a/vm/actor/src/util/set.rs b/vm/actor/src/util/set.rs index 045ad50a0f56..6c6ef9673edd 100644 --- a/vm/actor/src/util/set.rs +++ b/vm/actor/src/util/set.rs @@ -1,7 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::{BytesKey, EmptyType, EMPTY_VALUE, HAMT_BIT_WIDTH}; +use crate::{BytesKey, HAMT_BIT_WIDTH}; use cid::Cid; use ipld_blockstore::BlockStore; use ipld_hamt::{Error, Hamt}; @@ -41,13 +41,13 @@ where #[inline] pub fn put(&mut self, key: BytesKey) -> Result<(), String> { // Set hamt node to array root - Ok(self.0.set(key, EMPTY_VALUE)?) + Ok(self.0.set(key, ())?) } /// Checks if key exists in the set. #[inline] pub fn has(&self, key: &[u8]) -> Result { - Ok(self.0.get::<_, EmptyType>(key)?.is_some()) + Ok(self.0.get::<_, ()>(key)?.is_some()) } /// Deletes key from set. @@ -68,7 +68,7 @@ where // iterator should be Box to not convert to String and lose exit code Ok(self .0 - .for_each(|s, _: EmptyType| f(s).map_err(|e| e.to_string()))?) + .for_each(|s, _: ()| f(s).map_err(|e| e.to_string()))?) } /// Collects all keys from the set into a vector. diff --git a/vm/interpreter/src/vm.rs b/vm/interpreter/src/vm.rs index 234ccc49b076..7b7bc0dc9e5c 100644 --- a/vm/interpreter/src/vm.rs +++ b/vm/interpreter/src/vm.rs @@ -208,7 +208,7 @@ where if msg_gas_cost > msg.gas_limit() { return Ok(ApplyRet { msg_receipt: MessageReceipt { - return_data: Serialized::empty(), + return_data: Serialized::default(), exit_code: ExitCode::SysErrOutOfGas, gas_used: 0, }, @@ -224,7 +224,7 @@ where Err(_) => { return Ok(ApplyRet { msg_receipt: MessageReceipt { - return_data: Serialized::empty(), + return_data: Serialized::default(), exit_code: ExitCode::SysErrSenderInvalid, gas_used: 0, }, @@ -237,7 +237,7 @@ where if from_act.code != *ACCOUNT_ACTOR_CODE_ID { return Ok(ApplyRet { msg_receipt: MessageReceipt { - return_data: Serialized::empty(), + return_data: Serialized::default(), exit_code: ExitCode::SysErrSenderInvalid, gas_used: 0, }, @@ -250,7 +250,7 @@ where if msg.sequence() != from_act.sequence { return Ok(ApplyRet { msg_receipt: MessageReceipt { - return_data: Serialized::empty(), + return_data: Serialized::default(), exit_code: ExitCode::SysErrSenderStateInvalid, gas_used: 0, }, @@ -265,7 +265,7 @@ where if from_act.balance < total_cost { return Ok(ApplyRet { msg_receipt: MessageReceipt { - return_data: Serialized::empty(), + return_data: Serialized::default(), exit_code: ExitCode::SysErrSenderStateInvalid, gas_used: 0, }, @@ -318,7 +318,7 @@ where if let Err(e) = rt.charge_gas(rt.price_list().on_chain_return_value(ret_data.len())) { act_err = Some(e); - ret_data = Serialized::empty(); + ret_data = Serialized::default(); } } if rt.gas_used() < 0 { @@ -390,9 +390,9 @@ where match res { Ok(mut rt) => match vm_send(&mut rt, msg, gas_cost) { Ok(ser) => (ser, Some(rt), None), - Err(actor_err) => (Serialized::empty(), Some(rt), Some(actor_err)), + Err(actor_err) => (Serialized::default(), Some(rt), Some(actor_err)), }, - Err(e) => (Serialized::empty(), None, Some(e)), + Err(e) => (Serialized::default(), None, Some(e)), } } } diff --git a/vm/message/tests/message_json_test.rs b/vm/message/tests/message_json_test.rs index ba438aa2899a..ca2a133a7722 100644 --- a/vm/message/tests/message_json_test.rs +++ b/vm/message/tests/message_json_test.rs @@ -85,7 +85,7 @@ fn message_json_annotations() { "GasPrice": "9", "GasLimit": 8, "Method": 7, - "Params": "gA==" + "Params": "" }, "signed": { "Message": { @@ -97,7 +97,7 @@ fn message_json_annotations() { "GasPrice": "9", "GasLimit": 8, "Method": 7, - "Params": "gA==" + "Params": "" }, "Signature": { "Type": 2, diff --git a/vm/src/method.rs b/vm/src/method.rs index 822698cab1e5..6160f87a58b1 100644 --- a/vm/src/method.rs +++ b/vm/src/method.rs @@ -1,7 +1,6 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use super::EMPTY_ARR_BYTES; use encoding::{de, from_slice, ser, serde_bytes, to_vec, Cbor, Error as EncodingError}; use serde::{Deserialize, Serialize}; use std::ops::Deref; @@ -15,23 +14,13 @@ pub const METHOD_SEND: MethodNum = 0; pub const METHOD_CONSTRUCTOR: MethodNum = 1; /// Serialized bytes to be used as parameters into actor methods -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Hash, Eq)] +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Hash, Eq, Default)] #[serde(transparent)] pub struct Serialized { #[serde(with = "serde_bytes")] bytes: Vec, } -impl Default for Serialized { - /// Default serialized bytes is an empty array serialized - #[inline] - fn default() -> Self { - Self { - bytes: EMPTY_ARR_BYTES.clone(), - } - } -} - impl Cbor for Serialized {} impl Deref for Serialized { @@ -47,11 +36,6 @@ impl Serialized { Self { bytes } } - /// Empty bytes constructor. Used for empty return values. - pub fn empty() -> Self { - Self { bytes: Vec::new() } - } - /// Contructor for encoding Cbor encodable structure pub fn serialize(obj: O) -> Result { Ok(Self {