1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
use std::collections::BTreeMap;
use anyhow::Error;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::{
ipld_block::IpldBlock,
tuple::{serde_tuple, Deserialize_tuple, Serialize_tuple},
};
use fvm_shared4::{
address::Address,
clock::ChainEpoch,
consensus::ConsensusFault,
crypto::{
hash::SupportedHashes,
signature::{Signature, SECP_PUB_LEN, SECP_SIG_LEN, SECP_SIG_MESSAGE_HASH_SIZE},
},
econ::TokenAmount,
error::ExitCode,
piece::PieceInfo,
sector::{
AggregateSealVerifyProofAndInfos, RegisteredSealProof, ReplicaUpdateInfo, SealVerifyInfo,
WindowPoStVerifyInfo,
},
MethodNum,
};
use builtin::*;
pub use error::*;
use trace::*;
pub mod builtin;
mod error;
pub mod trace;
/// An abstract VM that is injected into integration tests
#[allow(clippy::type_complexity)]
pub trait VM {
/// Returns the underlying blockstore of the VM
fn blockstore(&self) -> &dyn Blockstore;
/// Get information about an actor
fn actor(&self, address: &Address) -> Option<ActorState>;
/// Upsert an actor into the state tree
fn set_actor(&self, key: &Address, a: ActorState);
/// Get the balance of the specified actor
fn balance(&self, address: &Address) -> TokenAmount;
/// Get the ID for the specified address
fn resolve_id_address(&self, address: &Address) -> Option<Address>;
/// Send a message between the two specified actors
fn execute_message(
&self,
from: &Address,
to: &Address,
value: &TokenAmount,
method: MethodNum,
params: Option<IpldBlock>,
) -> Result<MessageResult, VMError>;
/// Send a message without charging gas
fn execute_message_implicit(
&self,
from: &Address,
to: &Address,
value: &TokenAmount,
method: MethodNum,
params: Option<IpldBlock>,
) -> Result<MessageResult, VMError>;
/// Take all the invocations that have been made since the last call to this method
fn take_invocations(&self) -> Vec<InvocationTrace>;
/// Provides access to VM primitives
fn primitives(&self) -> &dyn Primitives;
/// Provides access to VM primitives that can be mocked
fn mut_primitives(&self) -> &dyn MockPrimitives;
/// Return a map of actor code CIDs to their corresponding types
fn actor_manifest(&self) -> BTreeMap<Cid, Type>;
/// Returns a map of all actor addresses to their corresponding states
fn actor_states(&self) -> BTreeMap<Address, ActorState>;
// Overridable constants and extern behaviour
/// Get the current chain epoch
fn epoch(&self) -> ChainEpoch;
/// Sets the epoch to the specified value
fn set_epoch(&self, epoch: ChainEpoch);
/// Get the circulating supply constant for the network
fn circulating_supply(&self) -> TokenAmount;
/// Set the circulating supply constant for the network
fn set_circulating_supply(&self, supply: TokenAmount);
/// Get the current base fee
fn base_fee(&self) -> TokenAmount;
/// Set the current base fee
fn set_base_fee(&self, amount: TokenAmount);
/// Get the current timestamp
fn timestamp(&self) -> u64;
/// Set the current timestamp
fn set_timestamp(&self, timestamp: u64);
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct MessageResult {
pub code: ExitCode,
pub message: String,
pub ret: Option<IpldBlock>,
}
// Duplicates an internal FVM type (fvm::state_tree::ActorState) that cannot be depended on here
#[derive(Serialize_tuple, Deserialize_tuple, Clone, PartialEq, Eq, Debug)]
pub struct ActorState {
/// Link to code for the actor.
pub code: Cid,
/// Link to the state of the actor.
pub state: Cid,
/// Sequence of the actor.
pub sequence: u64,
/// Tokens available to the actor.
pub balance: TokenAmount,
/// The actor's "delegated" address, if assigned.
///
/// This field is set on actor creation and never modified.
pub delegated_address: Option<Address>,
}
pub fn new_actor(
code: Cid,
state: Cid,
sequence: u64,
balance: TokenAmount,
delegated_address: Option<Address>,
) -> ActorState {
ActorState {
code,
state,
sequence,
balance,
delegated_address,
}
}
/// Pure functions implemented as primitives by the runtime.
pub trait Primitives {
/// Hashes input data using blake2b with 256 bit output.
fn hash_blake2b(&self, data: &[u8]) -> [u8; 32];
/// Hashes input data using a supported hash function.
fn hash(&self, hasher: SupportedHashes, data: &[u8]) -> Vec<u8>;
/// Hashes input into a 64 byte buffer
fn hash_64(&self, hasher: SupportedHashes, data: &[u8]) -> ([u8; 64], usize);
/// Computes an unsealed sector CID (CommD) from its constituent piece CIDs (CommPs) and sizes.
fn compute_unsealed_sector_cid(
&self,
proof_type: RegisteredSealProof,
pieces: &[PieceInfo],
) -> Result<Cid, Error>;
/// Verifies that a signature is valid for an address and plaintext.
fn verify_signature(
&self,
signature: &Signature,
signer: &Address,
plaintext: &[u8],
) -> Result<(), Error>;
fn recover_secp_public_key(
&self,
hash: &[u8; SECP_SIG_MESSAGE_HASH_SIZE],
signature: &[u8; SECP_SIG_LEN],
) -> Result<[u8; SECP_PUB_LEN], Error>;
/// Verifies a window proof of spacetime.
fn verify_post(&self, verify_info: &WindowPoStVerifyInfo) -> Result<(), anyhow::Error>;
/// Verifies that two block headers provide proof of a consensus fault:
/// - both headers mined by the same actor
/// - headers are different
/// - first header is of the same or lower epoch as the second
/// - at least one of the headers appears in the current chain at or after epoch `earliest`
/// - the headers provide evidence of a fault (see the spec for the different fault types).
///
/// The parameters are all serialized block headers. The third "extra" parameter is consulted only for
/// the "parent grinding fault", in which case it must be the sibling of h1 (same parent tipset) and one of the
/// blocks in the parent of h2 (i.e. h2's grandparent).
/// Returns nil and an error if the headers don't prove a fault.
fn verify_consensus_fault(
&self,
h1: &[u8],
h2: &[u8],
extra: &[u8],
) -> Result<Option<ConsensusFault>, anyhow::Error>;
fn batch_verify_seals(&self, batch: &[SealVerifyInfo]) -> anyhow::Result<Vec<bool>>;
fn verify_aggregate_seals(
&self,
aggregate: &AggregateSealVerifyProofAndInfos,
) -> Result<(), anyhow::Error>;
fn verify_replica_update(&self, replica: &ReplicaUpdateInfo) -> Result<(), anyhow::Error>;
}
#[allow(clippy::type_complexity)]
pub trait MockPrimitives: Primitives {
/// Override the primitive hash_blake2b function
fn override_hash_blake2b(&self, f: fn(&[u8]) -> [u8; 32]);
/// Override the primitive hash function
fn override_hash(&self, f: fn(SupportedHashes, &[u8]) -> Vec<u8>);
/// Override the primitive hash_64 function
fn override_hash_64(&self, f: fn(SupportedHashes, &[u8]) -> ([u8; 64], usize));
///Override the primitive compute_unsealed_sector_cid function
fn override_compute_unsealed_sector_cid(
&self,
f: fn(RegisteredSealProof, &[PieceInfo]) -> Result<Cid, Error>,
);
/// Override the primitive recover_secp_public_key function
fn override_recover_secp_public_key(
&self,
f: fn(
&[u8; SECP_SIG_MESSAGE_HASH_SIZE],
&[u8; SECP_SIG_LEN],
) -> Result<[u8; SECP_PUB_LEN], Error>,
);
/// Override the primitive verify_post function
fn override_verify_post(&self, f: fn(&WindowPoStVerifyInfo) -> Result<(), Error>);
/// Override the primitive verify_consensus_fault function
fn override_verify_consensus_fault(
&self,
f: fn(&[u8], &[u8], &[u8]) -> Result<Option<ConsensusFault>, Error>,
);
/// Override the primitive batch_verify_seals function
fn override_batch_verify_seals(&self, f: fn(&[SealVerifyInfo]) -> Result<Vec<bool>, Error>);
/// Override the primitive verify_aggregate_seals function
fn override_verify_aggregate_seals(
&self,
f: fn(&AggregateSealVerifyProofAndInfos) -> Result<(), Error>,
);
/// Override the primitive verify_signature function
fn override_verify_signature(&self, f: fn(&Signature, &Address, &[u8]) -> Result<(), Error>);
/// Override the primitive verify_replica_update function
fn override_verify_replica_update(&self, f: fn(&ReplicaUpdateInfo) -> Result<(), Error>);
fn as_primitives(&self) -> &dyn Primitives;
}