Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wenyuanhust authored Oct 20, 2023
2 parents 610a173 + 53f87df commit 0face9c
Show file tree
Hide file tree
Showing 45 changed files with 316 additions and 357 deletions.
108 changes: 108 additions & 0 deletions .github/workflows/hardfork_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Hardfork test

on:
push:
pull_request:
merge_group:
workflow_dispatch:

jobs:
hardfork-test:
strategy:
matrix:
# Supported GitHub-hosted runners and hardware resources
# see https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
os: [ubuntu-22.04]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Cache of Cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ matrix.os }}-${{ runner.os }}-${{ runner.arch }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ matrix.os }}-${{ runner.os }}-${{ runner.arch }}-cargo-build
- name: Build Axon in the development profile
run: cargo build

- name: Start multiple Axon nodes
env:
LOG_PATH: ${{ runner.temp }}/${{ matrix.os }}/multi-axon-nodes
run: |
echo "LOG_PATH: ${{ env.LOG_PATH }}"
mkdir -p ${{ env.LOG_PATH }}
target/debug/axon --version
sed -i 's/hardforks = \[\]/hardforks = ["None"]/g' devtools/chain/specs/multi_nodes/chain-spec.toml
grep "hardforks" devtools/chain/specs/multi_nodes/chain-spec.toml
for id in 1 2 3 4; do
target/debug/axon init \
--config devtools/chain/nodes/node_${id}.toml \
--chain-spec devtools/chain/specs/multi_nodes/chain-spec.toml \
> ${{ env.LOG_PATH }}/node_${id}.log
done
for id in 1 2 3 4; do
target/debug/axon run \
--config devtools/chain/nodes/node_${id}.toml \
>> ${{ env.LOG_PATH }}/node_${id}.log &
done
npx zx <<'EOF'
import { waitXBlocksPassed } from './devtools/ci/scripts/helper.js'
await Promise.all([
waitXBlocksPassed('http://127.0.0.1:8001', 4),
waitXBlocksPassed('http://127.0.0.1:8002', 4),
waitXBlocksPassed('http://127.0.0.1:8003', 4),
waitXBlocksPassed('http://127.0.0.1:8004', 4),
])
EOF
timeout-minutes: 1

- name: Checkout sunchengzhu/axon-hardfork-test
uses: actions/checkout@v4
with:
repository: sunchengzhu/axon-hardfork-test
path: axon-hardfork-test

- name: Run test cases before hardfork
working-directory: axon-hardfork-test
run: |
npm install
npx hardhat test --grep "deploy a normal contract"
npx hardhat test --grep "deploy a big contract larger than max_contract_limit"
npx hardhat test --grep "check hardfork info before hardfork"
- name: Hardfork
working-directory: axon-hardfork-test
run: |
bash hardfork.sh ../
- name: Run test cases after hardfork
working-directory: axon-hardfork-test
run: |
npx hardhat test --grep "check hardfork info after hardfork"
node_ids=(1 2 3 4)
random_value=$(( (RANDOM % ${#node_ids[@]}) + 1 ))
echo "Invoke system contract via node_"$random_value
npx hardhat test --grep "update max_contract_limit" --network "node_"$random_value
npx hardhat test --grep "deploy a big contract smaller than max_contract_limit"
- name: Archive logs
if: failure()
uses: actions/upload-artifact@v3
with:
name: multi-axon-nodes-logs
path: |
${{ runner.temp }}/${{ matrix.os }}/multi-axon-nodes/
66 changes: 57 additions & 9 deletions common/config-parser/src/types/config.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use std::{collections::HashMap, ffi::OsStr, io, net::SocketAddr, path::PathBuf};
use std::{
collections::HashMap,
ffi::OsStr,
fs::File,
io::{self, Read as _},
net::SocketAddr,
path::{Path, PathBuf},
};

use clap::builder::{StringValueParser, TypedValueParser, ValueParserFactory};
use serde::Deserialize;
use tentacle_multiaddr::MultiAddr;

use protocol::{
codec::deserialize_256bits_key,
types::{Key256Bits, H160},
};
use protocol::types::{Key256Bits, H160};

use crate::parse_file;

Expand All @@ -24,11 +28,13 @@ pub const DEFAULT_CACHE_SIZE: usize = 100;
pub struct Config {
// crypto
/// `net_privkey` is used for network connection.
#[serde(deserialize_with = "deserialize_256bits_key")]
pub net_privkey: Key256Bits,
#[serde(skip)]
pub net_privkey: Key256Bits,
pub net_privkey_file: PathBuf,
/// `bls_privkey` is used for signing consensus messages.
#[serde(deserialize_with = "deserialize_256bits_key")]
pub bls_privkey: Key256Bits,
#[serde(skip)]
pub bls_privkey: Key256Bits,
pub bls_privkey_file: PathBuf,

// db config
pub data_path: PathBuf,
Expand Down Expand Up @@ -124,9 +130,51 @@ impl TypedValueParser for ConfigValueParser {
);
clap::Error::raw(kind, msg)
})
.and_then(|mut config: Self::Value| {
let privkey_path = dir_path.join(&config.net_privkey_file);
config.net_privkey = load_privkey_from_file(&privkey_path)?;
Ok(config)
})
.and_then(|mut config: Self::Value| {
let privkey_path = dir_path.join(&config.bls_privkey_file);
config.bls_privkey = load_privkey_from_file(&privkey_path)?;
Ok(config)
})
}
}

fn load_privkey_from_file(privkey_path: &Path) -> Result<Key256Bits, clap::Error> {
File::open(privkey_path)
.and_then(|mut f| {
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).map(|_| buffer)
})
.map_err(|err| {
let kind = clap::error::ErrorKind::InvalidValue;
let msg = format!(
"failed to parse private key file {} since {err}",
privkey_path.display()
);
clap::Error::raw(kind, msg)
})
.and_then(|bytes| {
const LEN: usize = 32;
if bytes.len() == LEN {
let mut v = [0u8; 32];
v.copy_from_slice(&bytes);
Ok(Key256Bits::from(v))
} else {
let kind = clap::error::ErrorKind::InvalidValue;
let msg = format!(
"failed to parse private key file {} since its length is {} but expect {LEN}.",
privkey_path.display(),
bytes.len()
);
Err(clap::Error::raw(kind, msg))
}
})
}

#[derive(Clone, Debug, Deserialize)]
pub struct ConfigApi {
pub http_listening_address: Option<SocketAddr>,
Expand Down
22 changes: 16 additions & 6 deletions core/api/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ where
block_number: Option<u64>,
) -> ProtocolResult<Metadata> {
if let Some(num) = block_number {
return MetadataHandle::new(self.get_metadata_root(ctx).await?)
return MetadataHandle::new(self.get_metadata_root(ctx, Some(num)).await?)
.get_metadata_by_block_number(num);
}

Expand All @@ -255,11 +255,12 @@ where
.get_latest_block_header(ctx.clone())
.await?
.number;
MetadataHandle::new(self.get_metadata_root(ctx).await?).get_metadata_by_block_number(num)
MetadataHandle::new(self.get_metadata_root(ctx, None).await?)
.get_metadata_by_block_number(num)
}

async fn get_ckb_related_info(&self, ctx: Context) -> ProtocolResult<CkbRelatedInfo> {
MetadataHandle::new(self.get_metadata_root(ctx).await?).get_ckb_related_info()
MetadataHandle::new(self.get_metadata_root(ctx, None).await?).get_ckb_related_info()
}

async fn get_image_cell_root(&self, ctx: Context) -> ProtocolResult<H256> {
Expand All @@ -274,8 +275,17 @@ where
.get_image_cell_root())
}

async fn get_metadata_root(&self, ctx: Context) -> ProtocolResult<H256> {
let state_root = self.storage.get_latest_block_header(ctx).await?.state_root;
async fn get_metadata_root(&self, ctx: Context, number: Option<u64>) -> ProtocolResult<H256> {
let state_root = match number {
Some(n) => {
self.storage
.get_block_header(ctx, n)
.await?
.ok_or_else(|| APIError::RequestPayload("Not found number".to_string()))?
.state_root
}
None => self.storage.get_latest_block_header(ctx).await?.state_root,
};

Ok(AxonExecutorReadOnlyAdapter::from_root(
state_root,
Expand All @@ -287,7 +297,7 @@ where
}

async fn hardfork_info(&self, ctx: Context) -> ProtocolResult<HardforkInfo> {
MetadataHandle::new(self.get_metadata_root(ctx).await?).hardfork_infos()
MetadataHandle::new(self.get_metadata_root(ctx, None).await?).hardfork_infos()
}

async fn hardfork_proposal(&self, ctx: Context) -> ProtocolResult<Option<HardforkInfoInner>> {
Expand Down
8 changes: 4 additions & 4 deletions core/api/src/jsonrpc/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub enum RpcError {
#[display(fmt = "Invalid filter id {}", _0)]
CannotFindFilterId(u64),

#[display(fmt = "CKB-VM error {}", "decode_revert_msg(&_0.ret)")]
VM(TxResp),
#[display(fmt = "EVM error {}", "decode_revert_msg(&_0.ret)")]
Evm(TxResp),
#[display(fmt = "Internal error")]
Internal(String),
}
Expand Down Expand Up @@ -92,7 +92,7 @@ impl RpcError {
RpcError::InvalidFromBlockAndToBlockUnion => -40021,
RpcError::CannotFindFilterId(_) => -40022,

RpcError::VM(_) => -49998,
RpcError::Evm(_) => -49998,
RpcError::Internal(_) => -49999,
}
}
Expand Down Expand Up @@ -134,7 +134,7 @@ impl From<RpcError> for ErrorObjectOwned {
}
RpcError::CannotFindFilterId(_) => ErrorObject::owned(err_code, err, none_data),

RpcError::VM(resp) => {
RpcError::Evm(resp) => {
ErrorObject::owned(err_code, err.clone(), Some(vm_err(resp.clone())))
}
RpcError::Internal(msg) => ErrorObject::owned(err_code, err.clone(), Some(msg)),
Expand Down
4 changes: 2 additions & 2 deletions core/api/src/jsonrpc/impl/web3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
return Ok(call_hex_result);
}

Err(RpcError::VM(resp).into())
Err(RpcError::Evm(resp).into())
}

#[metrics_rpc("eth_estimateGas")]
Expand Down Expand Up @@ -557,7 +557,7 @@ impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
return Ok(resp.gas_used.into());
}

Err(RpcError::VM(resp).into())
Err(RpcError::Evm(resp).into())
}

#[metrics_rpc("eth_getCode")]
Expand Down
33 changes: 23 additions & 10 deletions core/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl Executor for AxonExecutor {
value: U256,
data: Vec<u8>,
) -> TxResp {
self.init_local_system_contract_roots(backend);
let config = self.config();
let metadata = StackSubstateMetadata::new(gas_limit, &config);
let state = MemoryStackState::new(metadata, backend);
Expand Down Expand Up @@ -139,9 +140,8 @@ impl Executor for AxonExecutor {
let mut encode_receipts = Vec::with_capacity(txs_len);
let (mut gas, mut fee) = (0u64, U256::zero());
let precompiles = build_precompile_set();
let config = self.config();

self.init_local_system_contract_roots(adapter);
let config = self.config();

// Execute system contracts before block hook.
before_block_hook(adapter);
Expand Down Expand Up @@ -394,7 +394,7 @@ impl AxonExecutor {
/// The `exec()` function is run in `tokio::task::block_in_place()` and all
/// the read or write operations are in the scope of exec function. The
/// thread context is not switched during exec function.
fn init_local_system_contract_roots<Adapter: ExecutorAdapter>(&self, adapter: &mut Adapter) {
fn init_local_system_contract_roots<Adapter: Backend>(&self, adapter: &Adapter) {
CURRENT_HEADER_CELL_ROOT.with(|root| {
*root.borrow_mut() =
adapter.storage(CKB_LIGHT_CLIENT_CONTRACT_ADDRESS, *HEADER_CELL_ROOT_KEY);
Expand All @@ -406,20 +406,22 @@ impl AxonExecutor {
}

fn config(&self) -> Config {
let mut config = Config::london();
let mut evm_config = Config::london();
let create_contract_limit = {
let latest_hardfork_info = &**HARDFORK_INFO.load();
let enable_contract_limit_flag = H256::from_low_u64_be(HardforkName::Andromeda as u64);
let enable_contract_limit_flag =
H256::from_low_u64_be((HardforkName::Andromeda as u64).to_be());
if latest_hardfork_info & &enable_contract_limit_flag == enable_contract_limit_flag {
let handle = MetadataHandle::new(CURRENT_METADATA_ROOT.with(|r| *r.borrow()));
let config = handle.get_consensus_config().unwrap();
Some(config.max_contract_limit as usize)
let consensus_config = handle.get_consensus_config().unwrap();
Some(consensus_config.max_contract_limit as usize)
} else {
None
// If the hardfork is not enabled, the limit is set to 0x6000
evm_config.create_contract_limit
}
};
config.create_contract_limit = create_contract_limit;
config
evm_config.create_contract_limit = create_contract_limit;
evm_config
}

#[cfg(test)]
Expand Down Expand Up @@ -512,3 +514,14 @@ pub fn is_call_system_script(action: &TransactionAction) -> bool {
pub fn is_transaction_call(action: &TransactionAction, addr: &H160) -> bool {
action == &TransactionAction::Call(*addr)
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_config_contract_limit() {
let config = Config::london();
assert_eq!(config.create_contract_limit, Some(0x6000));
}
}
7 changes: 5 additions & 2 deletions core/executor/src/tests/system_script/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,11 @@ fn prepare_validator() -> ValidatorExtend {
// .gas(21000)
// .nonce(nonce);

// let wallet = LocalWallet::from_str(PRIVATE_KEY).expect("failed to create
// wallet"); let tx = Legacy(transaction_request);
// let wallet = LocalWallet::from_str(PRIVATE_KEY).expect(
// "failed to create
// wallet",
// );
// let tx = Legacy(transaction_request);
// let signature: Signature = wallet.sign_transaction(&tx).await.unwrap();

// provider
Expand Down
Binary file added devtools/chain/bls.key
Binary file not shown.
Loading

0 comments on commit 0face9c

Please sign in to comment.