Merge branch 'master' into a5-improve-help
This commit is contained in:
commit
2e03cecf7b
|
@ -78,10 +78,10 @@ linux-stable:
|
||||||
#- export SHA3=$(target/release/pbtc tools hash target/release/pbtc)
|
#- export SHA3=$(target/release/pbtc tools hash target/release/pbtc)
|
||||||
- md5sum target/release/pbtc > pbtc.md5
|
- md5sum target/release/pbtc > pbtc.md5
|
||||||
- echo -en 'gitlab_fold:end:build.release'
|
- echo -en 'gitlab_fold:end:build.release'
|
||||||
- echo 'Running regtests from ./tools/compare-tool/pull-tests-be0eef7.jar' && echo -en 'gitlab_fold:start:regtests'
|
- echo 'Running regtests from ./tools/regtests.sh' && echo -en 'gitlab_fold:start:regtests'
|
||||||
- ./tools/regtests.sh
|
- ./tools/regtests.sh
|
||||||
- echo -en 'gitlab_fold:end:regtests'
|
- echo -en 'gitlab_fold:end:regtests'
|
||||||
- echo 'Running bench from /benhcer' && echo -en 'gitlab_fold:start:bench'
|
- echo 'Running bench from ./tools/bench.sh' && echo -en 'gitlab_fold:start:bench'
|
||||||
- ./tools/bench.sh
|
- ./tools/bench.sh
|
||||||
- echo -en 'gitlab_fold:end:bench'
|
- echo -en 'gitlab_fold:end:bench'
|
||||||
- sh tools/deb_build.sh amd64
|
- sh tools/deb_build.sh amd64
|
||||||
|
|
|
@ -31,10 +31,10 @@ script:
|
||||||
- echo 'Building in release mode' && echo -en 'travis_fold:start:build.release'
|
- echo 'Building in release mode' && echo -en 'travis_fold:start:build.release'
|
||||||
- cargo build --release
|
- cargo build --release
|
||||||
- echo -en 'travis_fold:end:build.release'
|
- echo -en 'travis_fold:end:build.release'
|
||||||
- echo 'Running regtests from ./tools/compare-tool/pull-tests-be0eef7.jar' && echo -en 'travis_fold:start:regtests'
|
- echo 'Running regtests from ./tools/regtests.sh' && echo -en 'travis_fold:start:regtests'
|
||||||
- ./tools/regtests.sh
|
- ./tools/regtests.sh
|
||||||
- echo -en 'travis_fold:end:regtests'
|
- echo -en 'travis_fold:end:regtests'
|
||||||
- echo 'Running bench from /benhcer' && echo -en 'travis_fold:start:bench'
|
- echo 'Running bench from ./tools/bench.sh' && echo -en 'travis_fold:start:bench'
|
||||||
- ./tools/bench.sh
|
- ./tools/bench.sh
|
||||||
- echo -en 'travis_fold:end:bench'
|
- echo -en 'travis_fold:end:bench'
|
||||||
after_success: |
|
after_success: |
|
||||||
|
|
119
README.md
119
README.md
|
@ -210,7 +210,124 @@ SUBCOMMANDS:
|
||||||
|
|
||||||
## JSON-RPC
|
## JSON-RPC
|
||||||
|
|
||||||
TODO
|
#### Network
|
||||||
|
|
||||||
|
The Parity-bitcoin `network` interface.
|
||||||
|
|
||||||
|
##### addnode
|
||||||
|
|
||||||
|
Add the node.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "add"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
Remove the node.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "remove"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
Connect to the node.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "onetry"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### getaddednodeinfo
|
||||||
|
|
||||||
|
Query info for all added nodes.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true] }' localhost:8332
|
||||||
|
|
||||||
|
Query info for the specified node.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true, "192.168.0.201"] }' localhost:8332
|
||||||
|
|
||||||
|
##### getconnectioncount
|
||||||
|
|
||||||
|
Get the peer count.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getconnectioncount", "params": [] }' localhost:8332
|
||||||
|
|
||||||
|
#### Blockchain
|
||||||
|
|
||||||
|
The Parity-bitcoin `blockchain` data interface.
|
||||||
|
|
||||||
|
##### getbestblockhash
|
||||||
|
|
||||||
|
Get hash of best block.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getbestblockhash", "params": [], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### getblockcount
|
||||||
|
|
||||||
|
Get height of best block.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getblockcount", "params": [], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### getblockhash
|
||||||
|
|
||||||
|
Get hash of block at given height.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getblockhash", "params": [0], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### getdifficulty
|
||||||
|
|
||||||
|
Get proof-of-work difficulty as a multiple of the minimum difficulty
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getdifficulty", "params": [], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### getblock
|
||||||
|
|
||||||
|
Get information on given block.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getblock", "params": ["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### gettxout
|
||||||
|
|
||||||
|
Get details about an unspent transaction output.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "gettxout", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", 0], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### gettxoutsetinfo
|
||||||
|
|
||||||
|
Get statistics about the unspent transaction output set.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "gettxoutsetinfo", "params": [], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
#### Miner
|
||||||
|
|
||||||
|
The Parity-bitcoin `miner` data interface.
|
||||||
|
|
||||||
|
##### getblocktemplate
|
||||||
|
|
||||||
|
Get block template for mining.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getblocktemplate", "params": [{"capabilities": ["coinbasetxn", "workid", "coinbase/append"]}], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
#### Raw
|
||||||
|
|
||||||
|
The Parity-bitcoin `raw` data interface.
|
||||||
|
|
||||||
|
|
||||||
|
##### getrawtransaction
|
||||||
|
|
||||||
|
Return the raw transaction data.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "getrawtransaction", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### decoderawtransaction
|
||||||
|
|
||||||
|
Return an object representing the serialized, hex-encoded transaction.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "decoderawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### createrawtransaction
|
||||||
|
|
||||||
|
Create a transaction spending the given inputs and creating new outputs.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "createrawtransaction", "params": [[{"txid":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","vout":0}],{"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa":0.01}], "id":1 }' localhost:8332
|
||||||
|
|
||||||
|
##### sendrawtransaction
|
||||||
|
|
||||||
|
Adds transaction to the memory pool && relays it to the peers.
|
||||||
|
|
||||||
|
curl -H 'content-type: application/json' --data-binary '{"jsonrpc": "2.0", "method": "sendrawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' localhost:8332
|
||||||
|
|
||||||
## Logging
|
## Logging
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ use chain::BlockHeader;
|
||||||
use {BlockRef, BlockHeaderProvider};
|
use {BlockRef, BlockHeaderProvider};
|
||||||
|
|
||||||
pub struct BlockAncestors<'a> {
|
pub struct BlockAncestors<'a> {
|
||||||
block: BlockRef,
|
block: Option<BlockRef>,
|
||||||
headers: &'a BlockHeaderProvider,
|
headers: &'a BlockHeaderProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BlockAncestors<'a> {
|
impl<'a> BlockAncestors<'a> {
|
||||||
pub fn new(block: BlockRef, headers: &'a BlockHeaderProvider) -> Self {
|
pub fn new(block: BlockRef, headers: &'a BlockHeaderProvider) -> Self {
|
||||||
BlockAncestors {
|
BlockAncestors {
|
||||||
block: block,
|
block: Some(block),
|
||||||
headers: headers,
|
headers: headers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ impl<'a> Iterator for BlockAncestors<'a> {
|
||||||
type Item = BlockHeader;
|
type Item = BlockHeader;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let result = self.headers.block_header(self.block.clone());
|
let result = self.block.take().and_then(|block| self.headers.block_header(block));
|
||||||
if let Some(ref header) = result {
|
self.block = match result {
|
||||||
self.block = BlockRef::Hash(header.previous_header_hash.clone());
|
Some(ref header) => Some(BlockRef::Hash(header.previous_header_hash.clone())),
|
||||||
}
|
None => None,
|
||||||
|
};
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ args:
|
||||||
value_name: URL
|
value_name: URL
|
||||||
- jsonrpc-apis:
|
- jsonrpc-apis:
|
||||||
long: jsonrpc-apis
|
long: jsonrpc-apis
|
||||||
help: Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API names.
|
help: Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. Available APIs are blockchain, network, miner, raw.
|
||||||
takes_value: true
|
takes_value: true
|
||||||
value_name: APIS
|
value_name: APIS
|
||||||
- jsonrpc-hosts:
|
- jsonrpc-hosts:
|
||||||
|
|
|
@ -11,31 +11,31 @@ build_rpc_trait! {
|
||||||
/// Parity-bitcoin blockchain data interface.
|
/// Parity-bitcoin blockchain data interface.
|
||||||
pub trait BlockChain {
|
pub trait BlockChain {
|
||||||
/// Get hash of best block.
|
/// Get hash of best block.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getbestblockhash", "params": [], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getbestblockhash", "params": [], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getbestblockhash")]
|
#[rpc(name = "getbestblockhash")]
|
||||||
fn best_block_hash(&self) -> Result<H256, Error>;
|
fn best_block_hash(&self) -> Result<H256, Error>;
|
||||||
/// Get height of best block.
|
/// Get height of best block.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblockcount", "params": [], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblockcount", "params": [], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getblockcount")]
|
#[rpc(name = "getblockcount")]
|
||||||
fn block_count(&self) -> Result<u32, Error>;
|
fn block_count(&self) -> Result<u32, Error>;
|
||||||
/// Get hash of block at given height.
|
/// Get hash of block at given height.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblockhash", "params": [0], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblockhash", "params": [0], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getblockhash")]
|
#[rpc(name = "getblockhash")]
|
||||||
fn block_hash(&self, u32) -> Result<H256, Error>;
|
fn block_hash(&self, u32) -> Result<H256, Error>;
|
||||||
/// Get proof-of-work difficulty as a multiple of the minimum difficulty
|
/// Get proof-of-work difficulty as a multiple of the minimum difficulty
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getdifficulty", "params": [], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getdifficulty", "params": [], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getdifficulty")]
|
#[rpc(name = "getdifficulty")]
|
||||||
fn difficulty(&self) -> Result<f64, Error>;
|
fn difficulty(&self) -> Result<f64, Error>;
|
||||||
/// Get information on given block.
|
/// Get information on given block.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblock", "params": ["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblock", "params": ["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getblock")]
|
#[rpc(name = "getblock")]
|
||||||
fn block(&self, H256, Trailing<bool>) -> Result<GetBlockResponse, Error>;
|
fn block(&self, H256, Trailing<bool>) -> Result<GetBlockResponse, Error>;
|
||||||
/// Get details about an unspent transaction output.
|
/// Get details about an unspent transaction output.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "gettxout", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", 0], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "gettxout", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", 0], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "gettxout")]
|
#[rpc(name = "gettxout")]
|
||||||
fn transaction_out(&self, H256, u32, Trailing<bool>) -> Result<GetTxOutResponse, Error>;
|
fn transaction_out(&self, H256, u32, Trailing<bool>) -> Result<GetTxOutResponse, Error>;
|
||||||
/// Get statistics about the unspent transaction output set.
|
/// Get statistics about the unspent transaction output set.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "gettxoutsetinfo", "params": [], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "gettxoutsetinfo", "params": [], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "gettxoutsetinfo")]
|
#[rpc(name = "gettxoutsetinfo")]
|
||||||
fn transaction_out_set_info(&self) -> Result<GetTxOutSetInfoResponse, Error>;
|
fn transaction_out_set_info(&self) -> Result<GetTxOutSetInfoResponse, Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ use jsonrpc_core::Error;
|
||||||
use v1::types::{BlockTemplate, BlockTemplateRequest};
|
use v1::types::{BlockTemplate, BlockTemplateRequest};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Partiy-bitcoin miner data interface.
|
/// Parity-bitcoin miner data interface.
|
||||||
pub trait Miner {
|
pub trait Miner {
|
||||||
/// Get block template for mining.
|
/// Get block template for mining.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblocktemplate", "params": [{"capabilities": ["coinbasetxn", "workid", "coinbase/append"]}], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getblocktemplate", "params": [{"capabilities": ["coinbasetxn", "workid", "coinbase/append"]}], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getblocktemplate")]
|
#[rpc(name = "getblocktemplate")]
|
||||||
fn get_block_template(&self, BlockTemplateRequest) -> Result<BlockTemplate, Error>;
|
fn get_block_template(&self, BlockTemplateRequest) -> Result<BlockTemplate, Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,18 @@ build_rpc_trait! {
|
||||||
/// Parity-bitcoin network interface
|
/// Parity-bitcoin network interface
|
||||||
pub trait Network {
|
pub trait Network {
|
||||||
/// Add/remove/connect to the node
|
/// Add/remove/connect to the node
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "add"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "add"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "remove"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "remove"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "onetry"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "onetry"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "addnode")]
|
#[rpc(name = "addnode")]
|
||||||
fn add_node(&self, String, AddNodeOperation) -> Result<(), Error>;
|
fn add_node(&self, String, AddNodeOperation) -> Result<(), Error>;
|
||||||
/// Query node(s) info
|
/// Query node(s) info
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true] }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true] }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true, "192.168.0.201"] }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true, "192.168.0.201"] }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getaddednodeinfo")]
|
#[rpc(name = "getaddednodeinfo")]
|
||||||
fn node_info(&self, bool, Trailing<String>) -> Result<Vec<NodeInfo>, Error>;
|
fn node_info(&self, bool, Trailing<String>) -> Result<Vec<NodeInfo>, Error>;
|
||||||
/// Query node(s) info
|
/// Query node(s) info
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getconnectioncount", "params": [] }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getconnectioncount", "params": [] }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getconnectioncount")]
|
#[rpc(name = "getconnectioncount")]
|
||||||
fn connection_count(&self) -> Result<usize, Error>;
|
fn connection_count(&self) -> Result<usize, Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,22 +9,22 @@ use v1::types::TransactionOutputs;
|
||||||
use v1::types::GetRawTransactionResponse;
|
use v1::types::GetRawTransactionResponse;
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Partiy-bitcoin raw data interface.
|
/// Parity-bitcoin raw data interface.
|
||||||
pub trait Raw {
|
pub trait Raw {
|
||||||
/// Adds transaction to the memory pool && relays it to the peers.
|
/// Adds transaction to the memory pool && relays it to the peers.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "sendrawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "sendrawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "sendrawtransaction")]
|
#[rpc(name = "sendrawtransaction")]
|
||||||
fn send_raw_transaction(&self, RawTransaction) -> Result<H256, Error>;
|
fn send_raw_transaction(&self, RawTransaction) -> Result<H256, Error>;
|
||||||
/// Create a transaction spending the given inputs and creating new outputs.
|
/// Create a transaction spending the given inputs and creating new outputs.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "createrawtransaction", "params": [[{"txid":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","vout":0}],{"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa":0.01}], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "createrawtransaction", "params": [[{"txid":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","vout":0}],{"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa":0.01}], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "createrawtransaction")]
|
#[rpc(name = "createrawtransaction")]
|
||||||
fn create_raw_transaction(&self, Vec<TransactionInput>, TransactionOutputs, Trailing<u32>) -> Result<RawTransaction, Error>;
|
fn create_raw_transaction(&self, Vec<TransactionInput>, TransactionOutputs, Trailing<u32>) -> Result<RawTransaction, Error>;
|
||||||
/// Return an object representing the serialized, hex-encoded transaction.
|
/// Return an object representing the serialized, hex-encoded transaction.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "decoderawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "decoderawtransaction", "params": ["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "decoderawtransaction")]
|
#[rpc(name = "decoderawtransaction")]
|
||||||
fn decode_raw_transaction(&self, RawTransaction) -> Result<Transaction, Error>;
|
fn decode_raw_transaction(&self, RawTransaction) -> Result<Transaction, Error>;
|
||||||
/// Return the raw transaction data.
|
/// Return the raw transaction data.
|
||||||
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getrawtransaction", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/
|
/// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "getrawtransaction", "params": ["4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/
|
||||||
#[rpc(name = "getrawtransaction")]
|
#[rpc(name = "getrawtransaction")]
|
||||||
fn get_raw_transaction(&self, H256, Trailing<bool>) -> Result<GetRawTransactionResponse, Error>;
|
fn get_raw_transaction(&self, H256, Trailing<bool>) -> Result<GetRawTransactionResponse, Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,8 @@ impl<'a> HeaderVersion<'a> {
|
||||||
|
|
||||||
fn check(&self) -> Result<(), Error> {
|
fn check(&self) -> Result<(), Error> {
|
||||||
if (self.header.raw.version < 2 && self.height >= self.consensus_params.bip34_height) ||
|
if (self.header.raw.version < 2 && self.height >= self.consensus_params.bip34_height) ||
|
||||||
(self.header.raw.version < 3 && self.height >= self.consensus_params.bip65_height) ||
|
(self.header.raw.version < 3 && self.height >= self.consensus_params.bip66_height) ||
|
||||||
(self.header.raw.version < 4 && self.height >= self.consensus_params.bip66_height) {
|
(self.header.raw.version < 4 && self.height >= self.consensus_params.bip65_height) {
|
||||||
Err(Error::OldVersionBlock)
|
Err(Error::OldVersionBlock)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use hash::H256;
|
||||||
use db::{BlockHeaderProvider, BlockRef, BlockAncestors, BlockIterator};
|
use db::{BlockHeaderProvider, BlockRef, BlockAncestors, BlockIterator};
|
||||||
use timestamp::median_timestamp;
|
use timestamp::median_timestamp;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
enum ThresholdState {
|
enum ThresholdState {
|
||||||
Defined,
|
Defined,
|
||||||
Started,
|
Started,
|
||||||
|
@ -73,7 +73,7 @@ impl Deployments {
|
||||||
match consensus.csv_deployment {
|
match consensus.csv_deployment {
|
||||||
Some(csv) => {
|
Some(csv) => {
|
||||||
let mut cache = self.cache.lock();
|
let mut cache = self.cache.lock();
|
||||||
threshold_state(&mut cache, csv, number, headers, consensus).is_active()
|
threshold_state(&mut cache, csv, number, headers, consensus.miner_confirmation_window, consensus.rule_change_activation_threshold).is_active()
|
||||||
},
|
},
|
||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ impl Deployments {
|
||||||
match consensus.segwit_deployment {
|
match consensus.segwit_deployment {
|
||||||
Some(segwit) => {
|
Some(segwit) => {
|
||||||
let mut cache = self.cache.lock();
|
let mut cache = self.cache.lock();
|
||||||
threshold_state(&mut cache, segwit, number, headers, consensus).is_active()
|
threshold_state(&mut cache, segwit, number, headers, consensus.miner_confirmation_window, consensus.rule_change_activation_threshold).is_active()
|
||||||
},
|
},
|
||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ impl<'a> BlockDeployments<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates threshold state of given deployment
|
/// Calculates threshold state of given deployment
|
||||||
fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, number: u32, headers: &BlockHeaderProvider, consensus: &ConsensusParams) -> ThresholdState {
|
fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, number: u32, headers: &BlockHeaderProvider, miner_confirmation_window: u32, rule_change_activation_threshold: u32) -> ThresholdState {
|
||||||
// deployments are checked using previous block index
|
// deployments are checked using previous block index
|
||||||
if let Some(activation) = deployment.activation {
|
if let Some(activation) = deployment.activation {
|
||||||
if activation <= number {
|
if activation <= number {
|
||||||
|
@ -121,8 +121,13 @@ fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, num
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// number is number of block which is currently validating
|
||||||
|
// => it is not in database
|
||||||
|
// we need to make all checks for previous blocks
|
||||||
|
let number = number.saturating_sub(1);
|
||||||
|
|
||||||
// get number of the first block in the period
|
// get number of the first block in the period
|
||||||
let number = first_of_the_period(number.saturating_sub(1), consensus.miner_confirmation_window);
|
let number = first_of_the_period(number, miner_confirmation_window);
|
||||||
|
|
||||||
let hash = match headers.block_header(BlockRef::Number(number)) {
|
let hash = match headers.block_header(BlockRef::Number(number)) {
|
||||||
Some(header) => header.hash(),
|
Some(header) => header.hash(),
|
||||||
|
@ -140,9 +145,8 @@ fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, num
|
||||||
if deployment_state.state.is_final() {
|
if deployment_state.state.is_final() {
|
||||||
return deployment_state.state
|
return deployment_state.state
|
||||||
}
|
}
|
||||||
let from_block = deployment_state.block_number + consensus.miner_confirmation_window;
|
|
||||||
let threshold_state = deployment_state.state;
|
let threshold_state = deployment_state.state;
|
||||||
let deployment_iter = ThresholdIterator::new(deployment, headers, from_block, consensus, threshold_state);
|
let deployment_iter = ThresholdIterator::new(deployment, headers, number, miner_confirmation_window, rule_change_activation_threshold, threshold_state);
|
||||||
let state = match deployment_iter.last() {
|
let state = match deployment_iter.last() {
|
||||||
Some(state) => state,
|
Some(state) => state,
|
||||||
None => DeploymentState {
|
None => DeploymentState {
|
||||||
|
@ -156,7 +160,7 @@ fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, num
|
||||||
result
|
result
|
||||||
},
|
},
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
let deployment_iter = ThresholdIterator::new(deployment, headers, 0, consensus, ThresholdState::Defined);
|
let deployment_iter = ThresholdIterator::new(deployment, headers, miner_confirmation_window - 1, miner_confirmation_window, rule_change_activation_threshold, ThresholdState::Defined);
|
||||||
let state = deployment_iter.last().unwrap_or_default();
|
let state = deployment_iter.last().unwrap_or_default();
|
||||||
let result = state.state;
|
let result = state.state;
|
||||||
entry.insert(state);
|
entry.insert(state);
|
||||||
|
@ -184,17 +188,19 @@ struct ThresholdIterator<'a> {
|
||||||
deployment: Deployment,
|
deployment: Deployment,
|
||||||
block_iterator: BlockIterator<'a>,
|
block_iterator: BlockIterator<'a>,
|
||||||
headers: &'a BlockHeaderProvider,
|
headers: &'a BlockHeaderProvider,
|
||||||
consensus: &'a ConsensusParams,
|
miner_confirmation_window: u32,
|
||||||
|
rule_change_activation_threshold: u32,
|
||||||
last_state: ThresholdState,
|
last_state: ThresholdState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ThresholdIterator<'a> {
|
impl<'a> ThresholdIterator<'a> {
|
||||||
fn new(deployment: Deployment, headers: &'a BlockHeaderProvider, to_check: u32, consensus: &'a ConsensusParams, state: ThresholdState) -> Self {
|
fn new(deployment: Deployment, headers: &'a BlockHeaderProvider, to_check: u32, miner_confirmation_window: u32, rule_change_activation_threshold: u32, state: ThresholdState) -> Self {
|
||||||
ThresholdIterator {
|
ThresholdIterator {
|
||||||
deployment: deployment,
|
deployment: deployment,
|
||||||
block_iterator: BlockIterator::new(to_check, consensus.miner_confirmation_window, headers),
|
block_iterator: BlockIterator::new(to_check, miner_confirmation_window, headers),
|
||||||
headers: headers,
|
headers: headers,
|
||||||
consensus: consensus,
|
miner_confirmation_window: miner_confirmation_window,
|
||||||
|
rule_change_activation_threshold: rule_change_activation_threshold,
|
||||||
last_state: state,
|
last_state: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,8 +229,8 @@ impl<'a> Iterator for ThresholdIterator<'a> {
|
||||||
if median >= self.deployment.timeout {
|
if median >= self.deployment.timeout {
|
||||||
self.last_state = ThresholdState::Failed;
|
self.last_state = ThresholdState::Failed;
|
||||||
} else {
|
} else {
|
||||||
let count = count_deployment_matches(block_number, self.headers, self.deployment, self.consensus.miner_confirmation_window);
|
let count = count_deployment_matches(block_number, self.headers, self.deployment, self.miner_confirmation_window);
|
||||||
if count >= self.consensus.rule_change_activation_threshold as usize {
|
if count >= self.rule_change_activation_threshold as usize {
|
||||||
self.last_state = ThresholdState::LockedIn;
|
self.last_state = ThresholdState::LockedIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +255,78 @@ impl<'a> Iterator for ThresholdIterator<'a> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::first_of_the_period;
|
use std::collections::HashMap;
|
||||||
|
use chain::BlockHeader;
|
||||||
|
use db::{BlockHeaderProvider, BlockRef};
|
||||||
|
use network::Deployment;
|
||||||
|
use hash::H256;
|
||||||
|
use primitives::bytes::Bytes;
|
||||||
|
use super::{DeploymentStateCache, ThresholdState, first_of_the_period, threshold_state};
|
||||||
|
|
||||||
|
const MINER_CONFIRMATION_WINDOW: u32 = 1000;
|
||||||
|
const RULE_CHANGE_ACTIVATION_THRESHOLD: u32 = 900;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct DeploymentHeaderProvider {
|
||||||
|
pub by_height: Vec<BlockHeader>,
|
||||||
|
pub by_hash: HashMap<H256, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeploymentHeaderProvider {
|
||||||
|
pub fn mine(&mut self, height: u32, time: u32, version: u32) {
|
||||||
|
let mut previous_header_hash = self.by_height.last().map(|h| h.previous_header_hash.clone()).unwrap_or(H256::default());
|
||||||
|
while self.by_height.len() < height as usize {
|
||||||
|
let header = BlockHeader {
|
||||||
|
version: version,
|
||||||
|
previous_header_hash: previous_header_hash,
|
||||||
|
merkle_root_hash: Default::default(),
|
||||||
|
time: time,
|
||||||
|
bits: 0.into(),
|
||||||
|
nonce: height,
|
||||||
|
};
|
||||||
|
previous_header_hash = header.hash();
|
||||||
|
|
||||||
|
self.by_height.push(header);
|
||||||
|
self.by_hash.insert(previous_header_hash.clone(), self.by_height.len() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockHeaderProvider for DeploymentHeaderProvider {
|
||||||
|
fn block_header_bytes(&self, _block_ref: BlockRef) -> Option<Bytes> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_header(&self, block_ref: BlockRef) -> Option<BlockHeader> {
|
||||||
|
match block_ref {
|
||||||
|
BlockRef::Number(height) => self.by_height.get(height as usize).cloned(),
|
||||||
|
BlockRef::Hash(hash) => self.by_hash.get(&hash).and_then(|height| self.by_height.get(*height)).cloned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_test_time(height: u32) -> u32 {
|
||||||
|
1415926536 + 600 * height
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_deployments() -> (DeploymentStateCache, DeploymentHeaderProvider, Deployment) {
|
||||||
|
let (mut cache, headers, deployment) = (
|
||||||
|
DeploymentStateCache::default(),
|
||||||
|
DeploymentHeaderProvider::default(),
|
||||||
|
Deployment {
|
||||||
|
name: "test",
|
||||||
|
bit: 0,
|
||||||
|
start_time: make_test_time(10000),
|
||||||
|
timeout: make_test_time(20000),
|
||||||
|
activation: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, 0, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), ThresholdState::Defined);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, 0, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), ThresholdState::Defined);
|
||||||
|
|
||||||
|
(cache, headers, deployment)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_first_of_the_period() {
|
fn test_first_of_the_period() {
|
||||||
|
@ -263,4 +340,125 @@ mod tests {
|
||||||
assert_eq!(8063, first_of_the_period(10000, window));
|
assert_eq!(8063, first_of_the_period(10000, window));
|
||||||
assert_eq!(8063, first_of_the_period(10001, window));
|
assert_eq!(8063, first_of_the_period(10001, window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/bitcoin/bitcoin/blob/a90e6d2bffc422ddcdb771c53aac0bceb970a2c4/src/test/versionbits_tests.cpp#L149
|
||||||
|
#[test]
|
||||||
|
fn test_threshold_state_defined_to_failed() {
|
||||||
|
let (mut cache, mut headers, deployment) = prepare_deployments();
|
||||||
|
let test_cases = vec![
|
||||||
|
(1, make_test_time(1), 0x20000001, ThresholdState::Defined),
|
||||||
|
(11, make_test_time(11), 0x20000001, ThresholdState::Defined),
|
||||||
|
(989, make_test_time(989), 0x20000001, ThresholdState::Defined),
|
||||||
|
(999, make_test_time(20000), 0x20000001, ThresholdState::Defined),
|
||||||
|
(1000, make_test_time(30000), 0x20000001, ThresholdState::Failed),
|
||||||
|
(1999, make_test_time(30001), 0x20000001, ThresholdState::Failed),
|
||||||
|
(2000, make_test_time(30002), 0x20000001, ThresholdState::Failed),
|
||||||
|
(2001, make_test_time(30003), 0x20000001, ThresholdState::Failed),
|
||||||
|
(2999, make_test_time(30004), 0x20000001, ThresholdState::Failed),
|
||||||
|
(3000, make_test_time(30005), 0x20000001, ThresholdState::Failed),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (height, time, version, state) in test_cases {
|
||||||
|
headers.mine(height, time, version);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/bitcoin/bitcoin/blob/a90e6d2bffc422ddcdb771c53aac0bceb970a2c4/src/test/versionbits_tests.cpp#L162
|
||||||
|
#[test]
|
||||||
|
fn test_threshold_state_defined_to_started_to_failed() {
|
||||||
|
let (mut cache, mut headers, deployment) = prepare_deployments();
|
||||||
|
let test_cases = vec![
|
||||||
|
(1, make_test_time(1), 0x20000000, ThresholdState::Defined),
|
||||||
|
(1000, make_test_time(10000) - 1, 0x20000001, ThresholdState::Defined),
|
||||||
|
(2000, make_test_time(10000), 0x20000001, ThresholdState::Started),
|
||||||
|
(2051, make_test_time(10010), 0x20000000, ThresholdState::Started),
|
||||||
|
(2950, make_test_time(10020), 0x20000001, ThresholdState::Started),
|
||||||
|
(3000, make_test_time(20000), 0x20000000, ThresholdState::Failed),
|
||||||
|
(4000, make_test_time(20010), 0x20000001, ThresholdState::Failed),
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
for (height, time, version, state) in test_cases {
|
||||||
|
headers.mine(height, time, version);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/bitcoin/bitcoin/blob/a90e6d2bffc422ddcdb771c53aac0bceb970a2c4/src/test/versionbits_tests.cpp#L172
|
||||||
|
#[test]
|
||||||
|
fn test_threshold_state_defined_to_started_to_failed_when_threshold_reached() {
|
||||||
|
let (mut cache, mut headers, deployment) = prepare_deployments();
|
||||||
|
let test_cases = vec![
|
||||||
|
(1, make_test_time(1), 0x20000000, ThresholdState::Defined),
|
||||||
|
(1000, make_test_time(10000) - 1, 0x20000001, ThresholdState::Defined),
|
||||||
|
(2000, make_test_time(10000), 0x20000001, ThresholdState::Started),
|
||||||
|
(2999, make_test_time(30000), 0x20000001, ThresholdState::Started),
|
||||||
|
(3000, make_test_time(30000), 0x20000001, ThresholdState::Failed),
|
||||||
|
(3999, make_test_time(30001), 0x20000000, ThresholdState::Failed),
|
||||||
|
(4000, make_test_time(30002), 0x20000000, ThresholdState::Failed),
|
||||||
|
(14333, make_test_time(30003), 0x20000000, ThresholdState::Failed),
|
||||||
|
(20000, make_test_time(40000), 0x20000000, ThresholdState::Failed),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (height, time, version, state) in test_cases {
|
||||||
|
headers.mine(height, time, version);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/bitcoin/bitcoin/blob/a90e6d2bffc422ddcdb771c53aac0bceb970a2c4/src/test/versionbits_tests.cpp#L184
|
||||||
|
#[test]
|
||||||
|
fn test_threshold_state_defined_to_started_to_lockedin() {
|
||||||
|
let (mut cache, mut headers, deployment) = prepare_deployments();
|
||||||
|
let test_cases = vec![
|
||||||
|
(1, make_test_time(1), 0x20000000, ThresholdState::Defined),
|
||||||
|
(1000, make_test_time(10000) - 1, 0x20000001, ThresholdState::Defined),
|
||||||
|
(2000, make_test_time(10000), 0x20000001, ThresholdState::Started),
|
||||||
|
(2050, make_test_time(10010), 0x20000000, ThresholdState::Started),
|
||||||
|
(2950, make_test_time(10020), 0x20000001, ThresholdState::Started),
|
||||||
|
(2999, make_test_time(19999), 0x20000000, ThresholdState::Started),
|
||||||
|
(3000, make_test_time(29999), 0x20000000, ThresholdState::LockedIn),
|
||||||
|
(3999, make_test_time(30001), 0x20000000, ThresholdState::LockedIn),
|
||||||
|
(4000, make_test_time(30002), 0x20000000, ThresholdState::Active),
|
||||||
|
(14333, make_test_time(30003), 0x20000000, ThresholdState::Active),
|
||||||
|
(24000, make_test_time(40000), 0x20000000, ThresholdState::Active),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (height, time, version, state) in test_cases {
|
||||||
|
headers.mine(height, time, version);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/bitcoin/bitcoin/blob/a90e6d2bffc422ddcdb771c53aac0bceb970a2c4/src/test/versionbits_tests.cpp#L198
|
||||||
|
#[test]
|
||||||
|
fn test_threshold_state_defined_multiple_to_started_multiple_to_failed() {
|
||||||
|
let (mut cache, mut headers, deployment) = prepare_deployments();
|
||||||
|
let test_cases = vec![
|
||||||
|
(999, make_test_time(999), 0x20000000, ThresholdState::Defined),
|
||||||
|
(1000, make_test_time(1000), 0x20000000, ThresholdState::Defined),
|
||||||
|
(2000, make_test_time(2000), 0x20000000, ThresholdState::Defined),
|
||||||
|
(3000, make_test_time(10000), 0x20000000, ThresholdState::Started),
|
||||||
|
(4000, make_test_time(10000), 0x20000000, ThresholdState::Started),
|
||||||
|
(5000, make_test_time(10000), 0x20000000, ThresholdState::Started),
|
||||||
|
(6000, make_test_time(20000), 0x20000000, ThresholdState::Failed),
|
||||||
|
(7000, make_test_time(20000), 0x20000001, ThresholdState::Failed),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (height, time, version, state) in test_cases {
|
||||||
|
headers.mine(height, time, version);
|
||||||
|
|
||||||
|
assert_eq!(threshold_state(&mut cache, deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
assert_eq!(threshold_state(&mut DeploymentStateCache::default(), deployment, height, &headers, MINER_CONFIRMATION_WINDOW, RULE_CHANGE_ACTIVATION_THRESHOLD), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue