pallet_revive: Account20 (#41)

Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
Cyrill Leutwiler
2024-09-04 12:42:41 +02:00
committed by GitHub
parent 7c934e5ca1
commit 393d90165e
8 changed files with 530 additions and 501 deletions
+46 -77
View File
@@ -11,13 +11,13 @@
//! differential: false,
//! balances: vec![(ALICE, 1_000_000_000)],
//! actions: vec![Instantiate {
//! origin: TestAccountId::Alice,
//! origin: TestAddress::Alice,
//! value: 0,
//! gas_limit: Some(GAS_LIMIT),
//! storage_deposit_limit: Some(DEPOSIT_LIMIT),
//! code: Code::Bytes(include_bytes!("../fixtures/Baseline.pvm").to_vec()),
//! data: vec![],
//! salt: vec![],
//! salt: Default::default(),
//! }],
//! }
//! .run();
@@ -25,41 +25,52 @@
use std::time::Duration;
use hex::{FromHex, FromHexError, ToHex};
use hex::{FromHex, ToHex};
use pallet_revive::AddressMapper;
use polkadot_sdk::*;
use polkadot_sdk::{
pallet_revive::{CollectEvents, ContractExecResult, ContractInstantiateResult, DebugInfo},
polkadot_runtime_common::BuildStorage,
polkadot_sdk_frame::testing_prelude::*,
sp_core::H160,
sp_keystore::{testing::MemoryKeystore, KeystoreExt},
sp_runtime::AccountId32,
};
use serde::{Deserialize, Serialize};
mod runtime;
mod specs;
use crate::runtime::*;
pub use crate::specs::*;
pub const ALICE: AccountId = AccountId::new([1u8; 32]);
pub const BOB: AccountId = AccountId::new([2u8; 32]);
pub const CHARLIE: AccountId = AccountId::new([3u8; 32]);
mod runtime;
mod specs;
const SPEC_MARKER_BEGIN: &str = "/* runner.json";
const SPEC_MARKER_END: &str = "*/";
/// The alice test account
pub const ALICE: H160 = H160([1u8; 20]);
/// The bob test account
pub const BOB: H160 = H160([2u8; 20]);
/// The charlie test account
pub const CHARLIE: H160 = H160([3u8; 20]);
/// Default gas limit
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);
/// Default deposit limit
pub const DEPOSIT_LIMIT: Balance = 10_000_000;
/// Externalities builder
#[derive(Default)]
pub struct ExtBuilder {
/// List of endowments at genesis
balance_genesis_config: Vec<(AccountId, Balance)>,
balance_genesis_config: Vec<(AccountId32, Balance)>,
}
impl ExtBuilder {
/// Set the balance of an account at genesis
fn balance_genesis_config(mut self, value: Vec<(AccountId, Balance)>) -> Self {
self.balance_genesis_config = value;
self
fn balance_genesis_config(self, value: Vec<(H160, Balance)>) -> Self {
Self {
balance_genesis_config: value
.iter()
.map(|(address, balance)| (AccountId::to_account_id(address), *balance))
.collect(),
}
}
/// Build the externalities
@@ -81,12 +92,6 @@ impl ExtBuilder {
}
}
/// Default gas limit
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);
/// Default deposit limit
pub const DEPOSIT_LIMIT: Balance = 10_000_000;
/// Expectation for a call
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerifyCallExpectation {
@@ -94,45 +99,45 @@ pub struct VerifyCallExpectation {
pub gas_consumed: Option<Weight>,
/// When provided, the expected output
#[serde(default, with = "hex")]
pub output: OptionalHex,
pub output: OptionalHex<Vec<u8>>,
///Expected call result
pub success: bool,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct OptionalHex(Option<Vec<u8>>);
pub struct OptionalHex<T>(Option<T>);
impl FromHex for OptionalHex {
type Error = FromHexError;
impl<I: FromHex + AsRef<[u8]>> FromHex for OptionalHex<I> {
type Error = <I as FromHex>::Error;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
let value = hex::decode(hex)?;
let value = I::from_hex(hex)?;
Ok(Self(Some(value)))
}
}
impl ToHex for &OptionalHex {
impl<I: AsRef<[u8]>> ToHex for &OptionalHex<I> {
fn encode_hex<T: std::iter::FromIterator<char>>(&self) -> T {
match self.0.as_ref() {
None => T::from_iter("".chars()),
Some(data) => T::from_iter(hex::encode(data).chars()),
Some(data) => I::encode_hex::<T>(data),
}
}
fn encode_hex_upper<T: std::iter::FromIterator<char>>(&self) -> T {
match self.0.as_ref() {
None => T::from_iter("".chars()),
Some(data) => T::from_iter(hex::encode_upper(data).chars()),
Some(data) => I::encode_hex_upper(data),
}
}
}
impl From<alloy_primitives::Bytes> for OptionalHex {
fn from(value: alloy_primitives::Bytes) -> Self {
if value.is_empty() {
impl<T: AsRef<[u8]>> From<T> for OptionalHex<T> {
fn from(value: T) -> Self {
if value.as_ref().is_empty() {
OptionalHex(None)
} else {
OptionalHex(Some(value.into()))
OptionalHex(Some(value))
}
}
}
@@ -155,9 +160,11 @@ impl VerifyCallExpectation {
result.is_ok(),
"contract execution result mismatch: {result:?}"
);
if let Some(gas_consumed) = self.gas_consumed {
assert_eq!(gas_consumed, result.gas_consumed());
}
if let OptionalHex(Some(data)) = self.output {
assert_eq!(data, result.output());
}
@@ -172,7 +179,7 @@ pub enum CallResult {
wall_time: Duration,
},
Instantiate {
result: ContractInstantiateResult<AccountId, Balance, EventRecord>,
result: ContractInstantiateResult<Balance, EventRecord>,
wall_time: Duration,
},
}
@@ -209,7 +216,7 @@ impl CallResult {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Code {
/// Compile a single solidity source and use the blob of `contract`
Solidity {
@@ -232,7 +239,7 @@ impl Default for Code {
}
}
impl From<Code> for pallet_revive::Code<Hash> {
impl From<Code> for pallet_revive::Code {
fn from(val: Code) -> Self {
match val {
Code::Solidity {
@@ -261,44 +268,6 @@ impl From<Code> for pallet_revive::Code<Hash> {
}
}
pub fn specs_from_comment(contract_name: &str, path: &str) -> Vec<Specs> {
let solidity = match std::fs::read_to_string(path) {
Err(err) => panic!("unable to read {path}: {err}"),
Ok(solidity) => solidity,
};
let mut json_string = String::with_capacity(solidity.len());
let mut is_reading = false;
let mut specs = Vec::new();
for line in solidity.lines() {
if line.starts_with(SPEC_MARKER_BEGIN) {
is_reading = true;
continue;
}
if is_reading {
if line.starts_with(SPEC_MARKER_END) {
match serde_json::from_str::<Specs>(&json_string) {
Ok(mut spec) => {
spec.replace_empty_code(contract_name, path);
specs.push(spec);
}
Err(e) => panic!("invalid spec JSON: {e}"),
}
is_reading = false;
json_string.clear();
continue;
}
json_string.push_str(line)
}
}
assert!(!specs.is_empty(), "source does not contain any test spec");
specs
}
#[cfg(test)]
mod tests {
use crate::*;
@@ -310,13 +279,13 @@ mod tests {
differential: false,
balances: vec![(ALICE, 1_000_000_000)],
actions: vec![Instantiate {
origin: TestAccountId::Alice,
origin: TestAddress::Alice,
value: 0,
gas_limit: Some(GAS_LIMIT),
storage_deposit_limit: Some(DEPOSIT_LIMIT),
code: Code::Bytes(include_bytes!("../fixtures/Baseline.pvm").to_vec()),
data: vec![],
salt: vec![],
salt: OptionalHex::default(),
}],
};
specs.run();
@@ -328,7 +297,7 @@ mod tests {
r#"
{
"balances": [
[ "5C62Ck4UrFPiBtoCmeSrgF7x9yv9mn38446dhCpsi2mLHiFT", 1000000000 ]
[ "0101010101010101010101010101010101010101", 1000000000 ]
],
"actions": [
{