diff --git a/.github/workflows/ci_unit_tests_windows.yaml b/.github/workflows/ci_unit_tests_windows.yaml index 97bfd92e6f..5ed4332b9d 100644 --- a/.github/workflows/ci_unit_tests_windows.yaml +++ b/.github/workflows/ci_unit_tests_windows.yaml @@ -62,8 +62,6 @@ jobs: scoop install git scoop bucket add extras scoop install llvm - - name: Install nextest dependency - run: scoop install jq - name: Install nextest-rs/nextest uses: taiki-e/install-action@nextest - run: | diff --git a/Cargo.lock b/Cargo.lock index 841878d27f..cc96553fd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,9 +150,9 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arc-swap" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "async-stream" @@ -407,9 +407,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -5457,18 +5457,18 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", @@ -5593,9 +5593,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", diff --git a/benches/benches/benchmarks/always_success.rs b/benches/benches/benchmarks/always_success.rs index dc5f0f205a..111766000f 100644 --- a/benches/benches/benchmarks/always_success.rs +++ b/benches/benches/benchmarks/always_success.rs @@ -44,7 +44,7 @@ fn bench(c: &mut Criterion) { |(chain, blocks)| { blocks.into_iter().skip(1).for_each(|block| { chain - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block OK"); }); }, @@ -187,7 +187,7 @@ fn bench(c: &mut Criterion) { |(chain, blocks)| { blocks.into_iter().skip(8).for_each(|block| { chain - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block OK"); }); }, diff --git a/benches/benches/benchmarks/overall.rs b/benches/benches/benchmarks/overall.rs index 74bf84b953..2f966e0318 100644 --- a/benches/benches/benchmarks/overall.rs +++ b/benches/benches/benchmarks/overall.rs @@ -20,6 +20,7 @@ use ckb_types::{ U256, }; use ckb_verification::HeaderVerifier; +use ckb_verification_traits::Switch; use ckb_verification_traits::Verifier; use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion}; use rand::random; @@ -217,7 +218,9 @@ fn bench(c: &mut Criterion) { .verify(&block.header()) .expect("header verified"); - chain.process_block(Arc::new(block)).expect("process_block"); + chain + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) + .expect("process_block"); i -= 1; } }, diff --git a/benches/benches/benchmarks/secp_2in2out.rs b/benches/benches/benchmarks/secp_2in2out.rs index 8dd3eb3d2d..69c0705f4f 100644 --- a/benches/benches/benchmarks/secp_2in2out.rs +++ b/benches/benches/benchmarks/secp_2in2out.rs @@ -44,7 +44,7 @@ fn bench(c: &mut Criterion) { |(chain, blocks)| { blocks.into_iter().skip(1).for_each(|block| { chain - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block OK"); }); }, @@ -187,7 +187,7 @@ fn bench(c: &mut Criterion) { |(chain, blocks)| { blocks.into_iter().skip(8).for_each(|block| { chain - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block OK"); }); }, diff --git a/chain/src/tests/basic.rs b/chain/src/tests/basic.rs index d9b7c1ece8..e8ad1bf182 100644 --- a/chain/src/tests/basic.rs +++ b/chain/src/tests/basic.rs @@ -34,7 +34,7 @@ fn repeat_process_block() { let block = Arc::new(chain.blocks().last().unwrap().clone()); assert!(chain_controller - .process_block(Arc::clone(&block)) + .internal_process_block(Arc::clone(&block), Switch::DISABLE_EXTENSION) .expect("process block ok")); assert_eq!( shared @@ -46,7 +46,7 @@ fn repeat_process_block() { ); assert!(!chain_controller - .process_block(Arc::clone(&block)) + .internal_process_block(Arc::clone(&block), Switch::DISABLE_EXTENSION) .expect("process block ok")); assert_eq!( shared @@ -165,7 +165,10 @@ fn test_transaction_spend_in_same_block() { for block in chain.blocks() { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } @@ -236,13 +239,16 @@ fn test_transaction_conflict_in_same_block() { for block in chain.blocks().iter().take(3) { chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); } assert_error_eq!( OutPointError::Dead(OutPoint::new(tx1_hash, 0)), chain_controller - .process_block(Arc::new(chain.blocks()[3].clone())) + .internal_process_block( + Arc::new(chain.blocks()[3].clone()), + Switch::DISABLE_EXTENSION + ) .unwrap_err(), ); } @@ -273,13 +279,16 @@ fn test_transaction_conflict_in_different_blocks() { for block in chain.blocks().iter().take(4) { chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); } assert_error_eq!( OutPointError::Unknown(OutPoint::new(tx1_hash, 0)), chain_controller - .process_block(Arc::new(chain.blocks()[4].clone())) + .internal_process_block( + Arc::new(chain.blocks()[4].clone()), + Switch::DISABLE_EXTENSION + ) .unwrap_err(), ); } @@ -307,13 +316,16 @@ fn test_invalid_out_point_index_in_same_block() { for block in chain.blocks().iter().take(3) { chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); } assert_error_eq!( OutPointError::Unknown(OutPoint::new(tx1_hash, 1)), chain_controller - .process_block(Arc::new(chain.blocks()[3].clone())) + .internal_process_block( + Arc::new(chain.blocks()[3].clone()), + Switch::DISABLE_EXTENSION + ) .unwrap_err(), ); } @@ -342,14 +354,17 @@ fn test_invalid_out_point_index_in_different_blocks() { for block in chain.blocks().iter().take(4) { chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); } assert_error_eq!( OutPointError::Unknown(OutPoint::new(tx1_hash, 1)), chain_controller - .process_block(Arc::new(chain.blocks()[4].clone())) + .internal_process_block( + Arc::new(chain.blocks()[4].clone()), + Switch::DISABLE_EXTENSION + ) .unwrap_err(), ); } diff --git a/chain/src/tests/delay_verify.rs b/chain/src/tests/delay_verify.rs index b2b8029edf..77ed3780b7 100644 --- a/chain/src/tests/delay_verify.rs +++ b/chain/src/tests/delay_verify.rs @@ -46,13 +46,19 @@ fn test_dead_cell_in_same_block() { for block in chain1.blocks() { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } for block in chain2.blocks().iter().take(switch_fork_number + 1) { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } @@ -61,7 +67,7 @@ fn test_dead_cell_in_same_block() { chain_controller .internal_process_block( Arc::new(chain2.blocks()[switch_fork_number + 1].clone()), - Switch::DISABLE_EPOCH, + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, ) .unwrap_err(), ) @@ -101,13 +107,19 @@ fn test_dead_cell_in_different_block() { for block in chain1.blocks() { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } for block in chain2.blocks().iter().take(switch_fork_number + 2) { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } @@ -116,7 +128,7 @@ fn test_dead_cell_in_different_block() { chain_controller .internal_process_block( Arc::new(chain2.blocks()[switch_fork_number + 2].clone()), - Switch::DISABLE_EPOCH, + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, ) .unwrap_err(), ); @@ -157,13 +169,19 @@ fn test_invalid_out_point_index_in_same_block() { for block in chain1.blocks() { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } for block in chain2.blocks().iter().take(switch_fork_number + 1) { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } @@ -172,7 +190,7 @@ fn test_invalid_out_point_index_in_same_block() { chain_controller .internal_process_block( Arc::new(chain2.blocks()[switch_fork_number + 1].clone()), - Switch::DISABLE_EPOCH, + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, ) .unwrap_err(), ) @@ -214,13 +232,19 @@ fn test_invalid_out_point_index_in_different_blocks() { for block in chain1.blocks() { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } for block in chain2.blocks().iter().take(switch_fork_number + 2) { chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); } @@ -229,7 +253,7 @@ fn test_invalid_out_point_index_in_different_blocks() { chain_controller .internal_process_block( Arc::new(chain2.blocks()[switch_fork_number + 2].clone()), - Switch::DISABLE_EPOCH, + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, ) .unwrap_err(), ); @@ -271,7 +295,10 @@ fn test_full_dead_transaction() { .build(); chain_controller - .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); mock_store.insert_block(&block, &epoch); @@ -346,7 +373,10 @@ fn test_full_dead_transaction() { .build() }; chain_controller - .internal_process_block(Arc::new(new_block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(new_block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); mock_store.insert_block(&new_block, &epoch); parent = new_block.header().to_owned(); @@ -426,7 +456,10 @@ fn test_full_dead_transaction() { .build() }; chain_controller - .internal_process_block(Arc::new(new_block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(new_block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); mock_store.insert_block(&new_block, &epoch); parent = new_block.header().to_owned(); @@ -495,7 +528,10 @@ fn test_full_dead_transaction() { .build() }; chain_controller - .internal_process_block(Arc::new(new_block.clone()), Switch::DISABLE_EPOCH) + .internal_process_block( + Arc::new(new_block.clone()), + Switch::DISABLE_EPOCH | Switch::DISABLE_EXTENSION, + ) .expect("process block ok"); mock_store.insert_block(&new_block, &epoch); parent = new_block.header().to_owned(); diff --git a/chain/src/tests/reward.rs b/chain/src/tests/reward.rs index 774fa6cd58..73de141c86 100644 --- a/chain/src/tests/reward.rs +++ b/chain/src/tests/reward.rs @@ -21,6 +21,7 @@ use ckb_types::{ }, utilities::DIFF_TWO, }; +use ckb_verification_traits::Switch; use std::sync::Arc; const TX_FEE: Capacity = capacity_bytes!(10); @@ -228,7 +229,7 @@ fn finalize_reward() { parent = block.header().clone(); chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); blocks.push(block); } @@ -265,7 +266,7 @@ fn finalize_reward() { parent = block.header(); chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("process block ok"); let (target, reward) = RewardCalculator::new(shared.consensus(), shared.snapshot().as_ref()) @@ -299,6 +300,6 @@ fn finalize_reward() { ); chain_controller - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block ok"); } diff --git a/deny.toml b/deny.toml index d847803a73..a3eba54265 100644 --- a/deny.toml +++ b/deny.toml @@ -4,12 +4,13 @@ unmaintained = "warn" yanked = "deny" notice = "deny" ignore = [ - # waiting https://github.com/bheisler/criterion.rs/pull/628 bump release - "RUSTSEC-2021-0145", # The CVE can be kept under control for its triggering. # See https://github.com/launchbadge/sqlx/pull/2455#issuecomment-1507657825 for more information. # Meanwhile, awaiting SQLx's new version (> 0.7.3) for full support of any DB driver. - "RUSTSEC-2022-0090" + "RUSTSEC-2022-0090", + # ckb-rich-indexer need sqlx's runtime-tokio-rustls feature, + # ignore https://rustsec.org/advisories/RUSTSEC-2024-0336 + "RUSTSEC-2024-0336" ] [licenses] diff --git a/devtools/doc/rpc-gen/src/gen.rs b/devtools/doc/rpc-gen/src/gen.rs index 69088dcef7..e21c132c43 100644 --- a/devtools/doc/rpc-gen/src/gen.rs +++ b/devtools/doc/rpc-gen/src/gen.rs @@ -142,7 +142,7 @@ impl RpcDocGenerator { }); } } - // sort rpc_methods accoring to title + // sort rpc_methods according to title rpc_methods.sort_by(|a, b| a.title.cmp(&b.title)); let mut all_types: Vec<(String, Value)> = pre_defined diff --git a/network/src/protocols/discovery/mod.rs b/network/src/protocols/discovery/mod.rs index b3e4548b26..c08012ba1b 100644 --- a/network/src/protocols/discovery/mod.rs +++ b/network/src/protocols/discovery/mod.rs @@ -271,7 +271,7 @@ fn verify_nodes_message(nodes: &Nodes) -> Option { if nodes.announce { if nodes.items.len() > ANNOUNCE_THRESHOLD { warn!( - "Number of nodes exceeds announce threshhold {}", + "Number of nodes exceeds announce threshold {}", ANNOUNCE_THRESHOLD ); misbehavior = Some(Misbehavior::TooManyItems { diff --git a/resource/src/lib.rs b/resource/src/lib.rs index 1f0c414547..eb29cf4b02 100644 --- a/resource/src/lib.rs +++ b/resource/src/lib.rs @@ -200,9 +200,9 @@ impl Resource { /// Exports a bundled resource. /// - /// This function returns `Ok` immediatly when invoked on a file system resource. + /// This function returns `Ok` immediately when invoked on a file system resource. /// - /// The file is exported to the path by combining `root_dir` and the resource indentifier. + /// The file is exported to the path by combining `root_dir` and the resource identifier. /// /// These bundled files can be customized for different chains using spec branches. /// See [Template](struct.Template.html). diff --git a/rpc/README.md b/rpc/README.md index 3ebc25f0a4..97cef9b2bc 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -105,6 +105,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.71.1. * [Module Pool](#module-pool) [👉 OpenRPC spec](http://playground.open-rpc.org/?uiSchema[appBar][ui:title]=CKB-Pool&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:logoUrl]=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/ckb-logo.jpg&schemaUrl=https://raw.githubusercontent.com/nervosnetwork/ckb-rpc-resources/develop/json/pool_rpc_doc.json) * [Method `send_transaction`](#pool-send_transaction) + * [Method `test_tx_pool_accept`](#pool-test_tx_pool_accept) * [Method `remove_transaction`](#pool-remove_transaction) * [Method `tx_pool_info`](#pool-tx_pool_info) * [Method `clear_tx_pool`](#pool-clear_tx_pool) @@ -163,6 +164,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.71.1. * [Type `DeploymentInfo`](#type-deploymentinfo) * [Type `DeploymentState`](#type-deploymentstate) * [Type `DeploymentsInfo`](#type-deploymentsinfo) + * [Type `EntryCompleted`](#type-entrycompleted) * [Type `EpochNumber`](#type-epochnumber) * [Type `EpochNumber`](#type-epochnumber) * [Type `EpochNumberWithFraction`](#type-epochnumberwithfraction) @@ -2444,7 +2446,7 @@ Response ``` * get cells by lock script and filter empty type script by setting script_len_range to -[0, 1), script_len is caculated by (code_hash + hash_type + args).len +[0, 1), script_len is calculated by (code_hash + hash_type + args).len Request @@ -3396,7 +3398,7 @@ Request "cycles_limit": "0xd09dc300", "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", "epoch": "0x7080019000001", - "extension": null, + "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", "number": "0x401", "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], @@ -3503,7 +3505,7 @@ Request "cycles_limit": "0xd09dc300", "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", "epoch": "0x7080019000001", - "extension": null, + "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", "number": "0x401", "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], @@ -3731,7 +3733,7 @@ Response "cycles_limit": "0xd09dc300", "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", "epoch": "0x7080019000001", - "extension": null, + "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", "number": "0x401", "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], @@ -4510,6 +4512,114 @@ Response } ``` + +#### Method `test_tx_pool_accept` +* `test_tx_pool_accept(tx, outputs_validator)` + * `tx`: [`Transaction`](#type-transaction) + * `outputs_validator`: [`OutputsValidator`](#type-outputsvalidator) `|` `null` +* result: [`EntryCompleted`](#type-entrycompleted) + +Test if a transaction can be accepted by the transaction pool without inserting it into the pool or rebroadcasting it to peers. +The parameters and errors of this method are the same as `send_transaction`. + +###### Params + +* `transaction` - The transaction. +* `outputs_validator` - Validates the transaction outputs before entering the tx-pool. (**Optional**, default is "passthrough"). + +###### Errors + +* [`PoolRejectedTransactionByOutputsValidator (-1102)`](../enum.RPCError.html#variant.PoolRejectedTransactionByOutputsValidator) - The transaction is rejected by the validator specified by `outputs_validator`. If you really want to send transactions with advanced scripts, please set `outputs_validator` to "passthrough". +* [`PoolRejectedTransactionByMinFeeRate (-1104)`](../enum.RPCError.html#variant.PoolRejectedTransactionByMinFeeRate) - The transaction fee rate must be greater than or equal to the config option `tx_pool.min_fee_rate`. +* [`PoolRejectedTransactionByMaxAncestorsCountLimit (-1105)`](../enum.RPCError.html#variant.PoolRejectedTransactionByMaxAncestorsCountLimit) - The ancestors count must be greater than or equal to the config option `tx_pool.max_ancestors_count`. +* [`PoolIsFull (-1106)`](../enum.RPCError.html#variant.PoolIsFull) - Pool is full. +* [`PoolRejectedDuplicatedTransaction (-1107)`](../enum.RPCError.html#variant.PoolRejectedDuplicatedTransaction) - The transaction is already in the pool. +* [`TransactionFailedToResolve (-301)`](../enum.RPCError.html#variant.TransactionFailedToResolve) - Failed to resolve the referenced cells and headers used in the transaction, as inputs or dependencies. +* [`TransactionFailedToVerify (-302)`](../enum.RPCError.html#variant.TransactionFailedToVerify) - Failed to verify the transaction. + +###### Examples + +Request + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "method": "test_tx_pool_accept", + "params": [ + { + "cell_deps": [ + { + "dep_type": "code", + "out_point": { + "index": "0x0", + "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3" + } + } + ], + "header_deps": [ + "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed" + ], + "inputs": [ + { + "previous_output": { + "index": "0x0", + "tx_hash": "0x075fe030c1f4725713c5aacf41c2f59b29b284008fdb786e5efd8a058be51d0c" + }, + "since": "0x0" + } + ], + "outputs": [ + { + "capacity": "0x2431ac129", + "lock": { + "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "version": "0x0", + "witnesses": [] + }, + "passthrough" + ] +} +``` + +Response + +```json +{ + "id": 42, + "jsonrpc": "2.0", + "result": { + "cycles": "0x219", + "fee": "0x2a66f36e90" + } +} +``` + + +The response looks like below if the transaction pool check fails + +```text +{ + "id": 42, + "jsonrpc": "2.0", + "result": null, + "error": { + "code": -1107, + "data": "Duplicated(Byte32(0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3))", + "message": "PoolRejectedDuplicatedTransaction: Transaction(Byte32(0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3)) already exists in transaction_pool" + } +} +``` + #### Method `remove_transaction` * `remove_transaction(tx_hash)` @@ -5829,6 +5939,17 @@ Chain information. * `hash`: [`H256`](#type-h256) - requested block hash +### Type `EntryCompleted` +Transaction's verify result by test_tx_pool_accept + +#### Fields + +`EntryCompleted` is a JSON object with the following fields. + +* `cycles`: [`Uint64`](#type-uint64) - Cached tx cycles + +* `fee`: [`Uint64`](#type-uint64) - Cached tx fee + ### Type `EpochNumber` Consecutive epoch number starting from 0. diff --git a/rpc/src/module/experiment.rs b/rpc/src/module/experiment.rs index 23d32aeea4..90e910dc1a 100644 --- a/rpc/src/module/experiment.rs +++ b/rpc/src/module/experiment.rs @@ -202,7 +202,7 @@ impl ExperimentRpc for ExperimentRpcImpl { match calculator.calculate_maximum_withdraw( &output, - core::Capacity::bytes(output_data.len()).expect("should not overlfow"), + core::Capacity::bytes(output_data.len()).expect("should not overflow"), &deposit_header_hash, &withdrawing_header_hash.pack(), ) { @@ -231,7 +231,7 @@ impl ExperimentRpc for ExperimentRpcImpl { match calculator.calculate_maximum_withdraw( &output, - core::Capacity::bytes(output_data.len()).expect("should not overlfow"), + core::Capacity::bytes(output_data.len()).expect("should not overflow"), &deposit_header_hash, &withdrawing_header_hash, ) { diff --git a/rpc/src/module/indexer.rs b/rpc/src/module/indexer.rs index 8b9932c02f..68ac3cab59 100644 --- a/rpc/src/module/indexer.rs +++ b/rpc/src/module/indexer.rs @@ -276,7 +276,7 @@ pub trait IndexerRpc { /// ``` /// /// * get cells by lock script and filter empty type script by setting script_len_range to - /// [0, 1), script_len is caculated by (code_hash + hash_type + args).len + /// [0, 1), script_len is calculated by (code_hash + hash_type + args).len /// /// Request /// diff --git a/rpc/src/module/miner.rs b/rpc/src/module/miner.rs index 76e100bd5a..814f12f91d 100644 --- a/rpc/src/module/miner.rs +++ b/rpc/src/module/miner.rs @@ -101,7 +101,7 @@ pub trait MinerRpc { /// "cycles_limit": "0xd09dc300", /// "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", /// "epoch": "0x7080019000001", - /// "extension": null, + /// "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", /// "number": "0x401", /// "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", /// "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], diff --git a/rpc/src/module/pool.rs b/rpc/src/module/pool.rs index dc081ae5fc..aab1071e0d 100644 --- a/rpc/src/module/pool.rs +++ b/rpc/src/module/pool.rs @@ -3,10 +3,11 @@ use async_trait::async_trait; use ckb_chain_spec::consensus::Consensus; use ckb_constant::hardfork::{mainnet, testnet}; use ckb_jsonrpc_types::{ - OutputsValidator, PoolTxDetailInfo, RawTxPool, Script, Transaction, TxPoolInfo, + EntryCompleted, OutputsValidator, PoolTxDetailInfo, RawTxPool, Script, Transaction, TxPoolInfo, }; use ckb_logger::error; use ckb_shared::shared::Shared; +use ckb_types::core::TransactionView; use ckb_types::{core, packed, prelude::*, H256}; use ckb_verification::{Since, SinceMetric}; use jsonrpc_core::Result; @@ -109,6 +110,113 @@ pub trait PoolRpc { outputs_validator: Option, ) -> Result; + /// Test if a transaction can be accepted by the transaction pool without inserting it into the pool or rebroadcasting it to peers. + /// The parameters and errors of this method are the same as `send_transaction`. + /// + /// ## Params + /// + /// * `transaction` - The transaction. + /// * `outputs_validator` - Validates the transaction outputs before entering the tx-pool. (**Optional**, default is "passthrough"). + /// + /// ## Errors + /// + /// * [`PoolRejectedTransactionByOutputsValidator (-1102)`](../enum.RPCError.html#variant.PoolRejectedTransactionByOutputsValidator) - The transaction is rejected by the validator specified by `outputs_validator`. If you really want to send transactions with advanced scripts, please set `outputs_validator` to "passthrough". + /// * [`PoolRejectedTransactionByMinFeeRate (-1104)`](../enum.RPCError.html#variant.PoolRejectedTransactionByMinFeeRate) - The transaction fee rate must be greater than or equal to the config option `tx_pool.min_fee_rate`. + /// * [`PoolRejectedTransactionByMaxAncestorsCountLimit (-1105)`](../enum.RPCError.html#variant.PoolRejectedTransactionByMaxAncestorsCountLimit) - The ancestors count must be greater than or equal to the config option `tx_pool.max_ancestors_count`. + /// * [`PoolIsFull (-1106)`](../enum.RPCError.html#variant.PoolIsFull) - Pool is full. + /// * [`PoolRejectedDuplicatedTransaction (-1107)`](../enum.RPCError.html#variant.PoolRejectedDuplicatedTransaction) - The transaction is already in the pool. + /// * [`TransactionFailedToResolve (-301)`](../enum.RPCError.html#variant.TransactionFailedToResolve) - Failed to resolve the referenced cells and headers used in the transaction, as inputs or dependencies. + /// * [`TransactionFailedToVerify (-302)`](../enum.RPCError.html#variant.TransactionFailedToVerify) - Failed to verify the transaction. + /// + /// ## Examples + /// + /// Request + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "method": "test_tx_pool_accept", + /// "params": [ + /// { + /// "cell_deps": [ + /// { + /// "dep_type": "code", + /// "out_point": { + /// "index": "0x0", + /// "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3" + /// } + /// } + /// ], + /// "header_deps": [ + /// "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed" + /// ], + /// "inputs": [ + /// { + /// "previous_output": { + /// "index": "0x0", + /// "tx_hash": "0x075fe030c1f4725713c5aacf41c2f59b29b284008fdb786e5efd8a058be51d0c" + /// }, + /// "since": "0x0" + /// } + /// ], + /// "outputs": [ + /// { + /// "capacity": "0x2431ac129", + /// "lock": { + /// "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5", + /// "hash_type": "data", + /// "args": "0x" + /// }, + /// "type": null + /// } + /// ], + /// "outputs_data": [ + /// "0x" + /// ], + /// "version": "0x0", + /// "witnesses": [] + /// }, + /// "passthrough" + /// ] + /// } + /// ``` + /// + /// Response + /// + /// ```json + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "result": { + /// "cycles": "0x219", + /// "fee": "0x2a66f36e90" + /// } + /// } + /// ``` + /// + /// + /// The response looks like below if the transaction pool check fails + /// + /// ```text + /// { + /// "id": 42, + /// "jsonrpc": "2.0", + /// "result": null, + /// "error": { + /// "code": -1107, + /// "data": "Duplicated(Byte32(0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3))", + /// "message": "PoolRejectedDuplicatedTransaction: Transaction(Byte32(0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3)) already exists in transaction_pool" + /// } + /// } + /// ``` + #[rpc(name = "test_tx_pool_accept")] + fn test_tx_pool_accept( + &self, + tx: Transaction, + outputs_validator: Option, + ) -> Result; + /// Removes a transaction and all transactions which depends on it from tx pool if it exists. /// /// ## Params @@ -359,6 +467,33 @@ impl PoolRpcImpl { well_known_type_scripts, } } + + fn check_output_validator( + &self, + outputs_validator: Option, + tx: &TransactionView, + ) -> Result<()> { + if let Err(e) = match outputs_validator { + None | Some(OutputsValidator::Passthrough) => Ok(()), + Some(OutputsValidator::WellKnownScriptsOnly) => WellKnownScriptsOnlyValidator::new( + self.shared.consensus(), + &self.well_known_lock_scripts, + &self.well_known_type_scripts, + ) + .validate(tx), + } { + return Err(RPCError::custom_with_data( + RPCError::PoolRejectedTransactionByOutputsValidator, + format!( + "The transaction is rejected by OutputsValidator set in params[1]: {}. \ + Please check the related information in https://github.com/nervosnetwork/ckb/wiki/Transaction-%C2%BB-Default-Outputs-Validator", + outputs_validator.unwrap_or(OutputsValidator::WellKnownScriptsOnly).json_display() + ), + e, + )); + } + Ok(()) + } } /// Build well known lock scripts @@ -452,25 +587,7 @@ impl PoolRpc for PoolRpcImpl { let tx: packed::Transaction = tx.into(); let tx: core::TransactionView = tx.into_view(); - if let Err(e) = match outputs_validator { - None | Some(OutputsValidator::Passthrough) => Ok(()), - Some(OutputsValidator::WellKnownScriptsOnly) => WellKnownScriptsOnlyValidator::new( - self.shared.consensus(), - &self.well_known_lock_scripts, - &self.well_known_type_scripts, - ) - .validate(&tx), - } { - return Err(RPCError::custom_with_data( - RPCError::PoolRejectedTransactionByOutputsValidator, - format!( - "The transaction is rejected by OutputsValidator set in params[1]: {}. \ - Please check the related information in https://github.com/nervosnetwork/ckb/wiki/Transaction-%C2%BB-Default-Outputs-Validator", - outputs_validator.unwrap_or(OutputsValidator::WellKnownScriptsOnly).json_display() - ), - e, - )); - } + self.check_output_validator(outputs_validator, &tx)?; let tx_pool = self.shared.tx_pool_controller(); let submit_tx = tx_pool.submit_local_tx(tx.clone()); @@ -487,6 +604,31 @@ impl PoolRpc for PoolRpcImpl { } } + fn test_tx_pool_accept( + &self, + tx: Transaction, + outputs_validator: Option, + ) -> Result { + let tx: packed::Transaction = tx.into(); + let tx: core::TransactionView = tx.into_view(); + + self.check_output_validator(outputs_validator, &tx)?; + + let tx_pool = self.shared.tx_pool_controller(); + + let test_accept_tx_reslt = tx_pool.test_accept_tx(tx).map_err(|e| { + error!("Send test_tx_pool_accept_tx request error {}", e); + RPCError::ckb_internal_error(e) + })?; + + test_accept_tx_reslt + .map(|test_accept_result| test_accept_result.into()) + .map_err(|reject| { + error!("Send test_tx_pool_accept_tx request error {}", reject); + RPCError::from_submit_transaction_reject(&reject) + }) + } + fn remove_transaction(&self, tx_hash: H256) -> Result { let tx_pool = self.shared.tx_pool_controller(); diff --git a/rpc/src/module/test.rs b/rpc/src/module/test.rs index add04c472c..7819deca37 100644 --- a/rpc/src/module/test.rs +++ b/rpc/src/module/test.rs @@ -355,7 +355,7 @@ pub trait IntegrationTestRpc { /// "cycles_limit": "0xd09dc300", /// "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", /// "epoch": "0x7080019000001", - /// "extension": null, + /// "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", /// "number": "0x401", /// "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", /// "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], @@ -458,7 +458,7 @@ pub trait IntegrationTestRpc { /// "cycles_limit": "0xd09dc300", /// "dao": "0xd495a106684401001e47c0ae1d5930009449d26e32380000000721efd0030000", /// "epoch": "0x7080019000001", - /// "extension": null, + /// "extension": "0xb0a0079f3778c0ba0d89d88b389c602cc18b8a0355d16c0713f8bfcee64b5f84", /// "number": "0x401", /// "parent_hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", /// "proposals": ["0xa0ef4eb5f4ceeb08a4c8"], diff --git a/rpc/src/server.rs b/rpc/src/server.rs index e164ddcdbb..9577e33d4f 100644 --- a/rpc/src/server.rs +++ b/rpc/src/server.rs @@ -187,7 +187,7 @@ async fn ping_handler() -> impl IntoResponse { "pong" } -/// used for compatible with old PRC error responce for GET +/// used for compatible with old PRC error response for GET async fn get_error_handler() -> impl IntoResponse { ( StatusCode::METHOD_NOT_ALLOWED, diff --git a/rpc/src/tests/setup.rs b/rpc/src/tests/setup.rs index 23b9ec8885..1428fc6d3e 100644 --- a/rpc/src/tests/setup.rs +++ b/rpc/src/tests/setup.rs @@ -14,6 +14,7 @@ use ckb_network_alert::alert_relayer::AlertRelayer; use ckb_notify::NotifyService; use ckb_shared::SharedBuilder; use ckb_sync::SyncShared; +use ckb_verification_traits::Switch; use serde_json::json; use std::collections::HashMap; use std::sync::Arc; @@ -131,7 +132,7 @@ pub(crate) fn setup_rpc_test_suite(height: u64, consensus: Option) -> for _ in 0..height { let block = next_block(&shared, &parent.header()); chain_controller - .process_block(Arc::new(block.clone())) + .internal_process_block(Arc::new(block.clone()), Switch::DISABLE_EXTENSION) .expect("processing new block should be ok"); parent = block; } @@ -258,7 +259,7 @@ pub(crate) fn setup_rpc_test_suite(height: u64, consensus: Option) -> ) .build(); chain_controller - .process_block(Arc::new(fork_block)) + .internal_process_block(Arc::new(fork_block), Switch::DISABLE_EXTENSION) .expect("processing new block should be ok"); } diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index 7488b24598..2d8a16c481 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -15,6 +15,7 @@ use crate::{ use ckb_constant::{ consensus::TAU, hardfork::{mainnet, testnet}, + softfork, }; use ckb_dao_utils::genesis_dao_data_with_satoshi_gift; use ckb_pow::{Pow, PowEngine}; @@ -94,8 +95,10 @@ pub(crate) const SATOSHI_PUBKEY_HASH: H160 = h160!("0x62e907b15cbf27d5425399ebf6 // only affects genesis cellbase's satoshi lock cells. pub(crate) const SATOSHI_CELL_OCCUPIED_RATIO: Ratio = Ratio::new(6, 10); -pub(crate) const LC_MAINNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(8, 10); -pub(crate) const TESTNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(3, 4); +/// The mainnet default activation_threshold +pub const LC_MAINNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(8, 10); +/// The testnet default activation_threshold +pub const TESTNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(3, 4); /// The starting block number from which the lock script size of a DAO withdrawing /// cell shall be limited @@ -999,6 +1002,16 @@ impl Consensus { &self.hardfork_switch } + /// Returns whether rfc0044 is active based on the epoch number + pub fn rfc0044_active(&self, target: EpochNumber) -> bool { + let rfc0044_active_epoch = match self.id.as_str() { + mainnet::CHAIN_SPEC_NAME => softfork::mainnet::RFC0044_ACTIVE_EPOCH, + testnet::CHAIN_SPEC_NAME => softfork::testnet::RFC0044_ACTIVE_EPOCH, + _ => 0, + }; + target >= rfc0044_active_epoch + } + /// Returns what version a new block should use. pub fn compute_versionbits( &self, @@ -1109,6 +1122,27 @@ impl From for ckb_jsonrpc_types::Consensus { ckb_jsonrpc_types::SoftFork::new_rfc0043(deployment.into()), ); } + match consensus.id.as_str() { + mainnet::CHAIN_SPEC_NAME => { + softforks.insert( + DeploymentPos::LightClient.into(), + ckb_jsonrpc_types::SoftFork::new_buried( + true, + softfork::mainnet::RFC0044_ACTIVE_EPOCH.into(), + ), + ); + } + testnet::CHAIN_SPEC_NAME => { + softforks.insert( + DeploymentPos::LightClient.into(), + ckb_jsonrpc_types::SoftFork::new_buried( + true, + softfork::testnet::RFC0044_ACTIVE_EPOCH.into(), + ), + ); + } + _ => {} + }; Self { id: consensus.id, genesis_hash: consensus.genesis_hash.unpack(), diff --git a/spec/src/lib.rs b/spec/src/lib.rs index 627e66c047..4e029bc6cb 100644 --- a/spec/src/lib.rs +++ b/spec/src/lib.rs @@ -12,8 +12,8 @@ use crate::consensus::{ build_genesis_dao_data, build_genesis_epoch_ext, Consensus, ConsensusBuilder, - LC_MAINNET_ACTIVATION_THRESHOLD, SATOSHI_CELL_OCCUPIED_RATIO, SATOSHI_PUBKEY_HASH, - TESTNET_ACTIVATION_THRESHOLD, TYPE_ID_CODE_HASH, + SATOSHI_CELL_OCCUPIED_RATIO, SATOSHI_PUBKEY_HASH, TESTNET_ACTIVATION_THRESHOLD, + TYPE_ID_CODE_HASH, }; use crate::versionbits::{ActiveMode, Deployment, DeploymentPos}; use ckb_constant::hardfork::{mainnet, testnet}; @@ -525,31 +525,11 @@ impl ChainSpec { fn softfork_deployments(&self) -> Option> { match self.name.as_str() { mainnet::CHAIN_SPEC_NAME => { - let mut deployments = HashMap::new(); - let light_client = Deployment { - bit: 1, - start: 8_282, // 2023/09/01 00:00:00 utc - timeout: 8_552, // 8_282 + 270 - min_activation_epoch: 8_648, // 2023/11/01 00:00:00 utc - period: 42, - active_mode: ActiveMode::Normal, - threshold: LC_MAINNET_ACTIVATION_THRESHOLD, - }; - deployments.insert(DeploymentPos::LightClient, light_client); + let deployments = HashMap::new(); Some(deployments) } testnet::CHAIN_SPEC_NAME => { - let mut deployments = HashMap::new(); - let light_client = Deployment { - bit: 1, - start: 5_346, // 2022/11/01 - timeout: 5_616, // 5_346 + 270 - min_activation_epoch: 5_676, // 2022/12/25 - period: 42, - active_mode: ActiveMode::Normal, - threshold: TESTNET_ACTIVATION_THRESHOLD, - }; - deployments.insert(DeploymentPos::LightClient, light_client); + let deployments = HashMap::new(); Some(deployments) } _ => { diff --git a/spec/src/tests/mod.rs b/spec/src/tests/mod.rs index 613381293b..ad621c1597 100644 --- a/spec/src/tests/mod.rs +++ b/spec/src/tests/mod.rs @@ -113,7 +113,7 @@ fn test_bundled_specs() { .map(|output| Unpack::::unpack(&output.capacity())) .try_fold(Capacity::zero(), Capacity::safe_add) .unwrap(); - // capacity for input and outpus should be same + // capacity for input and outputs should be same assert_eq!(input_capacity, outputs_capacity); // dep group tx has only one input diff --git a/sync/src/relayer/tests/compact_block_process.rs b/sync/src/relayer/tests/compact_block_process.rs index 17b64a1339..3088aae90c 100644 --- a/sync/src/relayer/tests/compact_block_process.rs +++ b/sync/src/relayer/tests/compact_block_process.rs @@ -16,6 +16,7 @@ use ckb_types::{ core::{BlockBuilder, Capacity, EpochNumberWithFraction, HeaderBuilder, TransactionBuilder}, packed::{self, CellInput, CellOutputBuilder, CompactBlock, OutPoint, ProposalShortId}, }; +use ckb_verification_traits::Switch; use std::collections::{HashMap, HashSet}; use std::sync::Arc; @@ -386,7 +387,9 @@ fn test_accept_block() { ChainService::new(relayer.shared().shared().to_owned(), proposal_window); chain_service.start::<&str>(None) }; - chain_controller.process_block(Arc::new(uncle)).unwrap(); + chain_controller + .internal_process_block(Arc::new(uncle), Switch::DISABLE_EXTENSION) + .unwrap(); } let mut prefilled_transactions_indexes = HashSet::new(); diff --git a/sync/src/synchronizer/mod.rs b/sync/src/synchronizer/mod.rs index 1ea3b32fb7..18c34204be 100644 --- a/sync/src/synchronizer/mod.rs +++ b/sync/src/synchronizer/mod.rs @@ -79,6 +79,7 @@ struct BlockFetchCMD { recv: channel::Receiver, can_start: CanStart, number: BlockNumber, + start_timestamp: u64, } impl BlockFetchCMD { @@ -123,19 +124,73 @@ impl BlockFetchCMD { if number != self.number && (number - self.number) % 10000 == 0 { self.number = number; + let remaining_headers_sync_log = self.reaming_headers_sync_log(); + info!( - "best known header number: {}, hash: {:#?}, \ - temporarily can't find assume valid target, hash: {:#?} \ - Please wait", + "best known header {}-{}, \ + CKB is syncing to latest Header to find the assume valid target: {}. \ + Please wait. {}", number, best_known.hash(), - assume_valid_target + assume_valid_target, + remaining_headers_sync_log ); } } } } + fn reaming_headers_sync_log(&self) -> String { + if let Some(remaining_headers_needed) = self.calc_time_need_to_reach_latest_tip_header() { + format!( + "Need {} minutes to sync to the latest Header.", + remaining_headers_needed.as_secs() / 60 + ) + } else { + "".to_string() + } + } + + // Timeline: + // + // |-------------------|--------------------------------|------------|----> + // Genesis (shared best timestamp) | now + // | | | | + // | (Sync point) (CKB process start) | + // | | | + // |--Synced Part------|------------ Remain to Sync -----------------| + // | | + // |------------------- CKB Chain Age -------------------------------| + // + fn calc_time_need_to_reach_latest_tip_header(&self) -> Option { + let genesis_timestamp = self + .sync_shared + .consensus() + .genesis_block() + .header() + .timestamp(); + let shared_best_timestamp = self.sync_shared.state().shared_best_header().timestamp(); + + let ckb_process_start_timestamp = self.start_timestamp; + + let now_timestamp = unix_time_as_millis(); + + let ckb_chain_age = now_timestamp.checked_sub(genesis_timestamp)?; + + let ckb_process_age = now_timestamp.checked_sub(ckb_process_start_timestamp)?; + + let has_synced_headers_age = shared_best_timestamp.checked_sub(genesis_timestamp)?; + + let ckb_sync_header_speed = has_synced_headers_age.checked_div(ckb_process_age)?; + + let sync_all_headers_timecost = ckb_chain_age.checked_div(ckb_sync_header_speed)?; + + let sync_remaining_headers_needed = + sync_all_headers_timecost.checked_sub(ckb_process_age)?; + + Some(Duration::from_millis(sync_remaining_headers_needed)) + } + fn run(&mut self, stop_signal: Receiver<()>) { loop { select! { @@ -655,6 +710,7 @@ impl Synchronizer { recv, number, can_start: CanStart::MinWorkNotReach, + start_timestamp: unix_time_as_millis(), } .run(stop_signal); }) diff --git a/sync/src/tests/sync_shared.rs b/sync/src/tests/sync_shared.rs index 9955ef84b7..b743a6d59c 100644 --- a/sync/src/tests/sync_shared.rs +++ b/sync/src/tests/sync_shared.rs @@ -5,7 +5,7 @@ use ckb_chain::chain::ChainService; use ckb_shared::SharedBuilder; use ckb_store::{self, ChainStore}; use ckb_test_chain_utils::always_success_cellbase; -use ckb_types::core::{BlockBuilder, BlockView, Capacity}; +use ckb_types::core::Capacity; use ckb_types::prelude::*; use std::sync::Arc; @@ -124,34 +124,29 @@ fn test_insert_parent_unknown_block() { #[test] fn test_switch_valid_fork() { - let (shared, chain) = build_chain(4); - let make_valid_block = |shared, parent_hash| -> BlockView { - let header = inherit_block(shared, &parent_hash).build().header(); - let timestamp = header.timestamp() + 3; - let cellbase = inherit_block(shared, &parent_hash).build().transactions()[0].clone(); - BlockBuilder::default() - .header(header) - .timestamp(timestamp.pack()) - .transaction(cellbase) - .build() - }; - + let (shared, chain) = build_chain(5); // Insert the valid fork. The fork blocks would not been verified until the fork switches as // the main chain. And `block_status_map` would mark the fork blocks as `BLOCK_STORED` - let block_number = 1; - let mut parent_hash = shared.store().get_block_hash(block_number).unwrap(); - for number in 0..=block_number { - let block_hash = shared.store().get_block_hash(number).unwrap(); - shared.store().get_block(&block_hash).unwrap(); - } + let fork_tip = 2; + let (fork_shared, fork_chain) = build_chain(fork_tip); + let fork_tip_hash = fork_shared.store().get_block_hash(fork_tip).unwrap(); let mut valid_fork = Vec::new(); - for _ in 2..shared.active_chain().tip_number() { - let block = make_valid_block(shared.shared(), parent_hash.clone()); + let mut parent_header = fork_shared + .store() + .get_block_header(&fork_tip_hash) + .unwrap(); + for _ in 3..shared.active_chain().tip_number() { + let block = inherit_block(fork_shared.shared(), &parent_header.hash()) + .timestamp((parent_header.timestamp() + 3).pack()) + .build(); + let arc_block = Arc::new(block.clone()); + assert!(fork_shared + .insert_new_block(&fork_chain, Arc::clone(&arc_block)) + .expect("insert fork"),); assert!(shared - .insert_new_block(&chain, Arc::new(block.clone())) + .insert_new_block(&chain, arc_block) .expect("insert fork"),); - - parent_hash = block.header().hash(); + parent_header = block.header().clone(); valid_fork.push(block); } for block in valid_fork.iter() { @@ -166,12 +161,17 @@ fn test_switch_valid_fork() { let tip_number = shared.active_chain().tip_number(); // Make the fork switch as the main chain. for _ in tip_number..tip_number + 2 { - let block = inherit_block(shared.shared(), &parent_hash.clone()).build(); + let block = inherit_block(fork_shared.shared(), &parent_header.hash()) + .timestamp((parent_header.timestamp() + 3).pack()) + .build(); + let arc_block = Arc::new(block.clone()); + assert!(fork_shared + .insert_new_block(&fork_chain, Arc::clone(&arc_block)) + .expect("insert fork"),); assert!(shared - .insert_new_block(&chain, Arc::new(block.clone())) + .insert_new_block(&chain, arc_block) .expect("insert fork"),); - - parent_hash = block.header().hash(); + parent_header = block.header().clone(); valid_fork.push(block); } for block in valid_fork.iter() { diff --git a/sync/src/tests/synchronizer/basic_sync.rs b/sync/src/tests/synchronizer/basic_sync.rs index 9c5c1977b6..0d1af241b6 100644 --- a/sync/src/tests/synchronizer/basic_sync.rs +++ b/sync/src/tests/synchronizer/basic_sync.rs @@ -43,7 +43,7 @@ fn basic_sync() { let (signal_tx1, signal_rx1) = bounded(DEFAULT_CHANNEL); node1.start(thread_name.clone(), signal_tx1, |data| { - let msg = packed::SyncMessage::from_slice(&data) + let msg = packed::SyncMessage::from_compatible_slice(&data) .expect("sync message") .to_enum(); // terminate thread after 3 blocks @@ -149,6 +149,12 @@ fn setup_node(height: u64) -> (TestNode, Shared) { .unwrap() }; + let chain_root = snapshot + .chain_root_mmr(block.header().number()) + .get_root() + .expect("chain root_mmr"); + let bytes = chain_root.calc_mmr_hash().as_bytes().pack(); + block = BlockBuilder::default() .transaction(cellbase) .parent_hash(block.header().hash()) @@ -157,6 +163,7 @@ fn setup_node(height: u64) -> (TestNode, Shared) { .timestamp(timestamp.pack()) .compact_target(epoch.compact_target().pack()) .dao(dao) + .extension(Some(bytes)) .build(); chain_controller diff --git a/sync/src/tests/synchronizer/functions.rs b/sync/src/tests/synchronizer/functions.rs index 8b71178d0c..4f181ba59b 100644 --- a/sync/src/tests/synchronizer/functions.rs +++ b/sync/src/tests/synchronizer/functions.rs @@ -105,6 +105,12 @@ fn gen_block( .dao_field([resolved_cellbase].iter(), parent_header) .unwrap() }; + let chain_root = shared + .snapshot() + .chain_root_mmr(parent_header.number()) + .get_root() + .expect("chain root_mmr"); + let bytes = chain_root.calc_mmr_hash().as_bytes().pack(); BlockBuilder::default() .transaction(cellbase) @@ -115,6 +121,7 @@ fn gen_block( .compact_target(epoch.compact_target().pack()) .nonce(nonce.pack()) .dao(dao) + .extension(Some(bytes)) .build() } @@ -137,7 +144,7 @@ fn insert_block( let block = gen_block(shared, &parent, &epoch, nonce); chain_controller - .process_block(Arc::new(block)) + .internal_process_block(Arc::new(block), Switch::DISABLE_EXTENSION) .expect("process block ok"); } diff --git a/sync/src/tests/util.rs b/sync/src/tests/util.rs index 0ccf5ba2e8..3149b80ba5 100644 --- a/sync/src/tests/util.rs +++ b/sync/src/tests/util.rs @@ -69,6 +69,13 @@ pub fn inherit_block(shared: &Shared, parent_hash: &Byte32) -> BlockBuilder { .unwrap() }; + let chain_root = shared + .snapshot() + .chain_root_mmr(parent_number) + .get_root() + .expect("chain root_mmr"); + let bytes = chain_root.calc_mmr_hash().as_bytes().pack(); + BlockBuilder::default() .parent_hash(parent_hash.to_owned()) .number((parent.header().number() + 1).pack()) @@ -77,6 +84,7 @@ pub fn inherit_block(shared: &Shared, parent_hash: &Byte32) -> BlockBuilder { .compact_target(epoch.compact_target().pack()) .dao(dao) .transaction(cellbase) + .extension(Some(bytes)) } pub fn inherit_cellbase(snapshot: &Snapshot, parent_number: BlockNumber) -> TransactionView { diff --git a/test/src/main.rs b/test/src/main.rs index 20daadf4e1..cef9c5a673 100644 --- a/test/src/main.rs +++ b/test/src/main.rs @@ -438,6 +438,8 @@ fn all_specs() -> Vec> { Box::new(PoolResurrect), Box::new(PoolResolveConflictAfterReorg), Box::new(InvalidHeaderDep), + // TODO fix this on windows platform + #[cfg(not(target_os = "windows"))] Box::new(PoolPersisted), Box::new(TransactionRelayBasic), Box::new(TransactionRelayLowFeeRate), diff --git a/test/src/node.rs b/test/src/node.rs index 0ab6d5be95..650c43533d 100644 --- a/test/src/node.rs +++ b/test/src/node.rs @@ -8,7 +8,7 @@ use ckb_chain_spec::ChainSpec; use ckb_error::AnyError; use ckb_jsonrpc_types::{BlockFilter, BlockTemplate, TxPoolInfo}; use ckb_jsonrpc_types::{PoolTxDetailInfo, TxStatus}; -use ckb_logger::{debug, error}; +use ckb_logger::{debug, error, info}; use ckb_resource::Resource; use ckb_types::{ bytes, @@ -67,7 +67,7 @@ impl Node { // Copy node template into node's working directory let cells_dir = working_dir.join("specs").join("cells"); - ckb_logger::info!("working_dir {:?}", working_dir); + info!("working_dir {:?}", working_dir); fs::create_dir_all(cells_dir).expect("create node's dir"); for file in &[ diff --git a/traits/src/epoch_provider.rs b/traits/src/epoch_provider.rs index eea178c289..10caf222ea 100644 --- a/traits/src/epoch_provider.rs +++ b/traits/src/epoch_provider.rs @@ -51,7 +51,7 @@ pub trait EpochProvider { /// Progress of block's corresponding epoch pub enum BlockEpoch { - /// Block is the tail block of epoch, provides extrat statistics for next epoch generating or verifying + /// Block is the tail block of epoch, provides extra statistics for next epoch generating or verifying TailBlock { /// epoch information epoch: EpochExt, diff --git a/tx-pool/src/block_assembler/mod.rs b/tx-pool/src/block_assembler/mod.rs index 381a263790..81acca0951 100644 --- a/tx-pool/src/block_assembler/mod.rs +++ b/tx-pool/src/block_assembler/mod.rs @@ -10,7 +10,6 @@ use crate::component::entry::TxEntry; use crate::error::BlockAssemblerError; pub use candidate_uncles::CandidateUncles; use ckb_app_config::BlockAssemblerConfig; -use ckb_chain_spec::versionbits::DeploymentPos; use ckb_dao::DaoCalculator; use ckb_error::{AnyError, InternalErrorKind}; use ckb_jsonrpc_types::{ @@ -527,7 +526,11 @@ impl BlockAssembler { pub(crate) fn build_extension(snapshot: &Snapshot) -> Result, AnyError> { let tip_header = snapshot.tip_header(); - let mmr_activate = snapshot.versionbits_active(DeploymentPos::LightClient); + // The use of the epoch number of the tip here leads to an off-by-one bug, + // so be careful, it needs to be preserved for consistency reasons and not fixed directly. + let mmr_activate = snapshot + .consensus() + .rfc0044_active(tip_header.epoch().number()); if mmr_activate { let chain_root = snapshot .chain_root_mmr(tip_header.number()) diff --git a/tx-pool/src/pool.rs b/tx-pool/src/pool.rs index e115c69462..6399f18602 100644 --- a/tx-pool/src/pool.rs +++ b/tx-pool/src/pool.rs @@ -233,7 +233,7 @@ impl TxPool { { for (entry, reject) in self.pool_map.resolve_conflict(tx) { debug!( - "removed {} for commited: {}", + "removed {} for committed: {}", entry.transaction().hash(), tx.hash() ); diff --git a/tx-pool/src/process.rs b/tx-pool/src/process.rs index 235c806869..78d0bf2430 100644 --- a/tx-pool/src/process.rs +++ b/tx-pool/src/process.rs @@ -314,6 +314,21 @@ impl TxPoolService { self.enqueue_verify_queue(tx.clone(), remote).await } + pub(crate) async fn test_accept_tx(&self, tx: TransactionView) -> Result { + // non contextual verify first + self.non_contextual_verify(&tx, None)?; + + if self.chunk_contains(&tx).await { + return Err(Reject::Duplicated(tx.hash())); + } + + if self.orphan_contains(&tx).await { + debug!("reject tx {} already in orphan pool", tx.hash()); + return Err(Reject::Duplicated(tx.hash())); + } + self._test_accept_tx(tx.clone()).await + } + pub(crate) async fn process_tx( &self, tx: TransactionView, @@ -709,6 +724,29 @@ impl TxPoolService { Some((Ok(verified), submit_snapshot)) } + pub(crate) async fn _test_accept_tx(&self, tx: TransactionView) -> Result { + let tx_hash = tx.hash(); + + let (pre_check_ret, snapshot) = self.pre_check(&tx).await; + + let (_tip_hash, rtx, status, _fee, _tx_size) = pre_check_ret?; + + // skip check the delay window + + let verify_cache = self.fetch_tx_verify_cache(&tx_hash).await; + let max_cycles = self.consensus.max_block_cycles(); + let tip_header = snapshot.tip_header(); + let tx_env = Arc::new(status.with_env(tip_header)); + + verify_rtx( + Arc::clone(&snapshot), + Arc::clone(&rtx), + tx_env, + &verify_cache, + max_cycles, + ) + } + pub(crate) async fn update_tx_pool_for_reorg( &self, detached_blocks: VecDeque, diff --git a/tx-pool/src/service.rs b/tx-pool/src/service.rs index 01d057f0d3..df230c3adc 100644 --- a/tx-pool/src/service.rs +++ b/tx-pool/src/service.rs @@ -21,7 +21,7 @@ use ckb_network::{NetworkController, PeerIndex}; use ckb_script::ChunkCommand; use ckb_snapshot::Snapshot; use ckb_stop_handler::new_tokio_exit_rx; -use ckb_types::core::tx_pool::{PoolTxDetailInfo, TransactionWithStatus, TxStatus}; +use ckb_types::core::tx_pool::{EntryCompleted, PoolTxDetailInfo, TransactionWithStatus, TxStatus}; use ckb_types::{ core::{ tx_pool::{Reject, TxPoolEntryInfo, TxPoolIds, TxPoolInfo, TRANSACTION_SIZE_LIMIT}, @@ -77,6 +77,8 @@ type BlockTemplateArgs = (Option, Option, Option); pub(crate) type SubmitTxResult = Result<(), Reject>; +pub(crate) type TestAcceptTxResult = Result; + type GetTxStatusResult = Result<(TxStatus, Option), AnyError>; type GetTransactionWithStatusResult = Result; type FetchTxsWithCyclesResult = Vec<(ProposalShortId, (TransactionView, Cycle))>; @@ -92,6 +94,7 @@ pub(crate) enum Message { BlockTemplate(Request), SubmitLocalTx(Request), RemoveLocalTx(Request), + TestAcceptTx(Request), SubmitRemoteTx(Request<(TransactionView, Cycle, PeerIndex), ()>), NotifyTxs(Notify>), FreshProposalsFilter(Request, Vec>), @@ -229,6 +232,13 @@ impl TxPoolController { send_message!(self, SubmitLocalTx, tx) } + /// test if a tx can be accepted by tx-pool + /// Won't be broadcasted to network + /// won't be insert to tx-pool + pub fn test_accept_tx(&self, tx: TransactionView) -> Result { + send_message!(self, TestAcceptTx, tx) + } + /// Remove tx from tx-pool pub fn remove_local_tx(&self, tx_hash: Byte32) -> Result { send_message!(self, RemoveLocalTx, tx_hash) @@ -710,6 +720,15 @@ async fn process(mut service: TxPoolService, message: Message) { error!("Responder sending remove_tx result failed {:?}", e); }; } + Message::TestAcceptTx(Request { + responder, + arguments: tx, + }) => { + let result = service.test_accept_tx(tx).await; + if let Err(e) = responder.send(result.map(|r| r.into())) { + error!("Responder sending test_accept_tx result failed {:?}", e); + }; + } Message::SubmitRemoteTx(Request { responder, arguments: (tx, declared_cycles, peer), diff --git a/util/constant/src/lib.rs b/util/constant/src/lib.rs index b4450a3026..41ce1df37b 100644 --- a/util/constant/src/lib.rs +++ b/util/constant/src/lib.rs @@ -4,6 +4,8 @@ pub mod consensus; /// hardfork constant pub mod hardfork; +/// softfork constant +pub mod softfork; /// store constant pub mod store; /// sync constant diff --git a/util/constant/src/softfork/mainnet.rs b/util/constant/src/softfork/mainnet.rs new file mode 100644 index 0000000000..8e7410120e --- /dev/null +++ b/util/constant/src/softfork/mainnet.rs @@ -0,0 +1,2 @@ +/// hardcode RFC0044 active epoch +pub const RFC0044_ACTIVE_EPOCH: u64 = 8651; diff --git a/util/constant/src/softfork/mod.rs b/util/constant/src/softfork/mod.rs new file mode 100644 index 0000000000..f6ffb9499e --- /dev/null +++ b/util/constant/src/softfork/mod.rs @@ -0,0 +1,4 @@ +/// Softfork constant for mainnet. +pub mod mainnet; +/// Softfork constant for testnet. +pub mod testnet; diff --git a/util/constant/src/softfork/testnet.rs b/util/constant/src/softfork/testnet.rs new file mode 100644 index 0000000000..7dab085d52 --- /dev/null +++ b/util/constant/src/softfork/testnet.rs @@ -0,0 +1,2 @@ +/// hardcode RFC0044 active epoch +pub const RFC0044_ACTIVE_EPOCH: u64 = 5711; diff --git a/util/jsonrpc-types/src/blockchain.rs b/util/jsonrpc-types/src/blockchain.rs index e6f3f04413..47fbfff606 100644 --- a/util/jsonrpc-types/src/blockchain.rs +++ b/util/jsonrpc-types/src/blockchain.rs @@ -1467,6 +1467,15 @@ impl SoftFork { rfc0043: deployment, }) } + + /// Construct new buried + pub fn new_buried(active: bool, epoch: EpochNumber) -> SoftFork { + SoftFork::Buried(Buried { + active, + epoch, + status: SoftForkStatus::Buried, + }) + } } /// Represent soft fork deployments where the activation epoch is diff --git a/util/jsonrpc-types/src/lib.rs b/util/jsonrpc-types/src/lib.rs index a183318d33..ac70de3ec3 100644 --- a/util/jsonrpc-types/src/lib.rs +++ b/util/jsonrpc-types/src/lib.rs @@ -45,8 +45,9 @@ pub use self::net::{ RemoteNodeProtocol, SyncState, }; pub use self::pool::{ - AncestorsScoreSortKey, OutputsValidator, PoolTransactionEntry, PoolTransactionReject, - PoolTxDetailInfo, RawTxPool, TxPoolEntries, TxPoolEntry, TxPoolIds, TxPoolInfo, + AncestorsScoreSortKey, EntryCompleted, OutputsValidator, PoolTransactionEntry, + PoolTransactionReject, PoolTxDetailInfo, RawTxPool, TxPoolEntries, TxPoolEntry, TxPoolIds, + TxPoolInfo, }; pub use self::proposal_short_id::ProposalShortId; pub use self::subscription::Topic; diff --git a/util/jsonrpc-types/src/pool.rs b/util/jsonrpc-types/src/pool.rs index 5fb26901f4..18f2052dd1 100644 --- a/util/jsonrpc-types/src/pool.rs +++ b/util/jsonrpc-types/src/pool.rs @@ -350,3 +350,21 @@ impl From for PoolTransactionReject { } } } + +/// Transaction's verify result by test_tx_pool_accept +#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)] +pub struct EntryCompleted { + /// Cached tx cycles + pub cycles: Cycle, + /// Cached tx fee + pub fee: Capacity, +} + +impl From for EntryCompleted { + fn from(value: ckb_types::core::EntryCompleted) -> Self { + Self { + cycles: value.cycles.into(), + fee: value.fee.into(), + } + } +} diff --git a/util/test-chain-utils/src/chain.rs b/util/test-chain-utils/src/chain.rs index 2239ee3373..7669089979 100644 --- a/util/test-chain-utils/src/chain.rs +++ b/util/test-chain-utils/src/chain.rs @@ -5,7 +5,6 @@ use ckb_chain_spec::{ }; use ckb_dao_utils::genesis_dao_data; use ckb_resource::Resource; -use ckb_systemtime::unix_time_as_millis; use ckb_types::{ bytes::Bytes, core::{ @@ -125,6 +124,8 @@ pub fn load_is_even() -> &'static (CellOutput, Bytes, Script) { &LOAD_IS_EVEN } +const GENESIS_TIMESTAMP: u64 = 1_557_310_743; + /// Build and return an always success consensus instance. #[doc(hidden)] pub fn always_success_consensus() -> Consensus { @@ -138,7 +139,7 @@ pub fn always_success_consensus() -> Consensus { .build(); let dao = genesis_dao_data(vec![&always_success_tx]).unwrap(); let genesis = BlockBuilder::default() - .timestamp(unix_time_as_millis().pack()) + .timestamp(GENESIS_TIMESTAMP.pack()) .compact_target(difficulty_to_compact(U256::from(1000u64)).pack()) .dao(dao) .transaction(always_success_tx) diff --git a/util/types/src/core/mod.rs b/util/types/src/core/mod.rs index ae8602a577..5b0cbdb5b3 100644 --- a/util/types/src/core/mod.rs +++ b/util/types/src/core/mod.rs @@ -34,7 +34,7 @@ pub use extras::{BlockExt, EpochExt, EpochNumberWithFraction, TransactionInfo}; pub use fee_rate::FeeRate; pub use reward::{BlockEconomicState, BlockIssuance, BlockReward, MinerReward}; pub use transaction_meta::{TransactionMeta, TransactionMetaBuilder}; -pub use tx_pool::TransactionWithStatus; +pub use tx_pool::{EntryCompleted, TransactionWithStatus}; pub use views::{ BlockView, ExtraHashView, HeaderView, TransactionView, UncleBlockVecView, UncleBlockView, }; diff --git a/util/types/src/core/tx_pool.rs b/util/types/src/core/tx_pool.rs index 0a6f3187e8..1ca23a061f 100644 --- a/util/types/src/core/tx_pool.rs +++ b/util/types/src/core/tx_pool.rs @@ -395,3 +395,12 @@ impl PoolTxDetailInfo { } } } + +/// A Tx CacheEntry +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct EntryCompleted { + /// Cached tx cycles + pub cycles: Cycle, + /// Cached tx fee + pub fee: Capacity, +} diff --git a/verification/contextual/src/contextual_block_verifier.rs b/verification/contextual/src/contextual_block_verifier.rs index 132b4e3ca0..2a45886682 100644 --- a/verification/contextual/src/contextual_block_verifier.rs +++ b/verification/contextual/src/contextual_block_verifier.rs @@ -2,7 +2,7 @@ use crate::uncles_verifier::{UncleProvider, UnclesVerifier}; use ckb_async_runtime::Handle; use ckb_chain_spec::{ consensus::{Consensus, ConsensusProvider}, - versionbits::{DeploymentPos, ThresholdState, VersionbitsIndexer}, + versionbits::VersionbitsIndexer, }; use ckb_dao::DaoCalculator; use ckb_dao_utils::DaoError; @@ -63,13 +63,6 @@ impl VerifyContext { ) -> Result<(Script, BlockReward), DaoError> { RewardCalculator::new(&self.consensus, self.store.as_ref()).block_reward_to_finalize(parent) } - - fn versionbits_active(&self, pos: DeploymentPos, header: &HeaderView) -> bool { - self.consensus - .versionbits_state(pos, header, self.store.as_ref()) - .map(|state| state == ThresholdState::Active) - .unwrap_or(false) - } } impl HeaderProvider for VerifyContext { @@ -448,7 +441,7 @@ impl<'a, 'b, CS: ChainStore + VersionbitsIndexer + 'static> BlockTxsVerifier<'a, }) .map(|completed| (tx_hash, completed)) }.and_then(|result| { - if self.context.versionbits_active(DeploymentPos::LightClient, self.parent) { + if self.context.consensus.rfc0044_active(self.parent.epoch().number()) { DaoScriptSizeVerifier::new( Arc::clone(tx), Arc::clone(&self.context.consensus), @@ -545,8 +538,8 @@ impl<'a, 'b, CS: ChainStore + VersionbitsIndexer, MS: MMRStore> let mmr_active = self .context - .versionbits_active(DeploymentPos::LightClient, self.parent); - + .consensus + .rfc0044_active(self.parent.epoch().number()); match extra_fields_count { 0 => { if mmr_active { @@ -681,7 +674,10 @@ impl<'a, CS: ChainStore + VersionbitsIndexer + 'static, MS: MMRStore for EntryCompleted { + fn from(value: Completed) -> Self { + EntryCompleted { + cycles: value.cycles, + fee: value.fee, + } + } +} diff --git a/verification/traits/src/lib.rs b/verification/traits/src/lib.rs index 14473e25ef..e406c8a0b1 100644 --- a/verification/traits/src/lib.rs +++ b/verification/traits/src/lib.rs @@ -39,11 +39,15 @@ bitflags! { /// Disable script verification const DISABLE_SCRIPT = 0b01000000; + /// Disable extension verification + const DISABLE_EXTENSION = 0b10000000; + /// Disable all verifier const DISABLE_ALL = Self::DISABLE_EPOCH.bits | Self::DISABLE_UNCLES.bits | Self::DISABLE_TWO_PHASE_COMMIT.bits | Self::DISABLE_DAOHEADER.bits | Self::DISABLE_REWARD.bits | - Self::DISABLE_NON_CONTEXTUAL.bits | Self::DISABLE_SCRIPT.bits; + Self::DISABLE_NON_CONTEXTUAL.bits | Self::DISABLE_SCRIPT.bits | + Self::DISABLE_EXTENSION.bits; /// Only script verification const ONLY_SCRIPT = Self::DISABLE_ALL.bits & (!Self::DISABLE_SCRIPT.bits); @@ -86,6 +90,11 @@ impl Switch { self.contains(Switch::DISABLE_REWARD) } + /// Whether extension verifier is disabled + pub fn disable_extension(&self) -> bool { + self.contains(Switch::DISABLE_EXTENSION) + } + /// Whether script verifier is disabled pub fn disable_script(&self) -> bool { self.contains(Switch::DISABLE_SCRIPT)