From 13462c71b9a4d90289036790d3974cf6b9597005 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Tue, 29 Aug 2017 16:09:24 +0200 Subject: [PATCH 1/8] Fix type in CI scripts --- .gitlab-ci.yml | 4 ++-- .travis.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b092c58..2c38ef4b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,10 +78,10 @@ linux-stable: #- export SHA3=$(target/release/pbtc tools hash target/release/pbtc) - md5sum target/release/pbtc > pbtc.md5 - 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 - 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 - echo -en 'gitlab_fold:end:bench' - sh tools/deb_build.sh amd64 diff --git a/.travis.yml b/.travis.yml index 06af0e77..234d1230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,10 +31,10 @@ script: - echo 'Building in release mode' && echo -en 'travis_fold:start:build.release' - cargo 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 - 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 - echo -en 'travis_fold:end:bench' after_success: | From 3db431aa8e794e2c14aa490e515bab0e1818f824 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 31 Aug 2017 09:34:00 +0300 Subject: [PATCH 2/8] added deployments tests from bitcoin + fixes --- db/src/block_ancestors.rs | 13 +- verification/src/deployments.rs | 228 +++++++++++++++++++++++++++++--- 2 files changed, 220 insertions(+), 21 deletions(-) diff --git a/db/src/block_ancestors.rs b/db/src/block_ancestors.rs index 72974738..73d4df12 100644 --- a/db/src/block_ancestors.rs +++ b/db/src/block_ancestors.rs @@ -2,14 +2,14 @@ use chain::BlockHeader; use {BlockRef, BlockHeaderProvider}; pub struct BlockAncestors<'a> { - block: BlockRef, + block: Option, headers: &'a BlockHeaderProvider, } impl<'a> BlockAncestors<'a> { pub fn new(block: BlockRef, headers: &'a BlockHeaderProvider) -> Self { BlockAncestors { - block: block, + block: Some(block), headers: headers, } } @@ -19,10 +19,11 @@ impl<'a> Iterator for BlockAncestors<'a> { type Item = BlockHeader; fn next(&mut self) -> Option { - let result = self.headers.block_header(self.block.clone()); - if let Some(ref header) = result { - self.block = BlockRef::Hash(header.previous_header_hash.clone()); - } + let result = self.block.take().and_then(|block| self.headers.block_header(block)); + self.block = match result { + Some(ref header) => Some(BlockRef::Hash(header.previous_header_hash.clone())), + None => None, + }; result } } diff --git a/verification/src/deployments.rs b/verification/src/deployments.rs index 7aaf6157..7d4b2343 100644 --- a/verification/src/deployments.rs +++ b/verification/src/deployments.rs @@ -6,7 +6,7 @@ use hash::H256; use db::{BlockHeaderProvider, BlockRef, BlockAncestors, BlockIterator}; use timestamp::median_timestamp; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] enum ThresholdState { Defined, Started, @@ -73,7 +73,7 @@ impl Deployments { match consensus.csv_deployment { Some(csv) => { 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 } @@ -84,7 +84,7 @@ impl Deployments { match consensus.segwit_deployment { Some(segwit) => { 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 } @@ -111,7 +111,7 @@ impl<'a> BlockDeployments<'a> { } /// 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 if let Some(activation) = deployment.activation { 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 - 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)) { Some(header) => header.hash(), @@ -140,9 +145,8 @@ fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, num if deployment_state.state.is_final() { return deployment_state.state } - let from_block = deployment_state.block_number + consensus.miner_confirmation_window; 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() { Some(state) => state, None => DeploymentState { @@ -156,7 +160,7 @@ fn threshold_state(cache: &mut DeploymentStateCache, deployment: Deployment, num result }, 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 result = state.state; entry.insert(state); @@ -184,17 +188,19 @@ struct ThresholdIterator<'a> { deployment: Deployment, block_iterator: BlockIterator<'a>, headers: &'a BlockHeaderProvider, - consensus: &'a ConsensusParams, + miner_confirmation_window: u32, + rule_change_activation_threshold: u32, last_state: ThresholdState, } 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 { 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, - consensus: consensus, + miner_confirmation_window: miner_confirmation_window, + rule_change_activation_threshold: rule_change_activation_threshold, last_state: state, } } @@ -223,8 +229,8 @@ impl<'a> Iterator for ThresholdIterator<'a> { if median >= self.deployment.timeout { self.last_state = ThresholdState::Failed; } else { - let count = count_deployment_matches(block_number, self.headers, self.deployment, self.consensus.miner_confirmation_window); - if count >= self.consensus.rule_change_activation_threshold as usize { + let count = count_deployment_matches(block_number, self.headers, self.deployment, self.miner_confirmation_window); + if count >= self.rule_change_activation_threshold as usize { self.last_state = ThresholdState::LockedIn; } } @@ -249,7 +255,78 @@ impl<'a> Iterator for ThresholdIterator<'a> { #[cfg(test)] 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, + pub by_hash: HashMap, + } + + 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 { + unimplemented!() + } + + fn block_header(&self, block_ref: BlockRef) -> Option { + 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] 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(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); + } + } } From df74f6fb2b88dff9700da1f7c47a610dc6186ec0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 31 Aug 2017 10:39:53 +0300 Subject: [PATCH 3/8] fixed HeaderVersion check --- verification/src/accept_header.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/verification/src/accept_header.rs b/verification/src/accept_header.rs index 256b7b7c..7b23e3f7 100644 --- a/verification/src/accept_header.rs +++ b/verification/src/accept_header.rs @@ -54,8 +54,8 @@ impl<'a> HeaderVersion<'a> { fn check(&self) -> Result<(), Error> { 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 < 4 && self.height >= self.consensus_params.bip66_height) { + (self.header.raw.version < 3 && self.height >= self.consensus_params.bip66_height) || + (self.header.raw.version < 4 && self.height >= self.consensus_params.bip65_height) { Err(Error::OldVersionBlock) } else { Ok(()) From e6cadced031717a79a16ac070082ab012ca7a579 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 31 Aug 2017 16:14:04 +0200 Subject: [PATCH 4/8] Fix typos in rpc docs. --- rpc/src/v1/traits/blockchain.rs | 14 +++++++------- rpc/src/v1/traits/miner.rs | 4 ++-- rpc/src/v1/traits/network.rs | 12 ++++++------ rpc/src/v1/traits/raw.rs | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/rpc/src/v1/traits/blockchain.rs b/rpc/src/v1/traits/blockchain.rs index 2c2c1451..8e07baf3 100644 --- a/rpc/src/v1/traits/blockchain.rs +++ b/rpc/src/v1/traits/blockchain.rs @@ -11,31 +11,31 @@ build_rpc_trait! { /// Parity-bitcoin blockchain data interface. pub trait BlockChain { /// 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")] fn best_block_hash(&self) -> Result; /// 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")] fn block_count(&self) -> Result; /// 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")] fn block_hash(&self, u32) -> Result; /// 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")] fn difficulty(&self) -> Result; /// 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")] fn block(&self, H256, Trailing) -> Result; /// 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")] fn transaction_out(&self, H256, u32, Trailing) -> Result; /// 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")] fn transaction_out_set_info(&self) -> Result; } diff --git a/rpc/src/v1/traits/miner.rs b/rpc/src/v1/traits/miner.rs index 1c67114f..e7bdbd89 100644 --- a/rpc/src/v1/traits/miner.rs +++ b/rpc/src/v1/traits/miner.rs @@ -3,10 +3,10 @@ use jsonrpc_core::Error; use v1::types::{BlockTemplate, BlockTemplateRequest}; build_rpc_trait! { - /// Partiy-bitcoin miner data interface. + /// Parity-bitcoin miner data interface. pub trait Miner { /// 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")] fn get_block_template(&self, BlockTemplateRequest) -> Result; } diff --git a/rpc/src/v1/traits/network.rs b/rpc/src/v1/traits/network.rs index 5fcc0004..29b83e27 100644 --- a/rpc/src/v1/traits/network.rs +++ b/rpc/src/v1/traits/network.rs @@ -6,18 +6,18 @@ build_rpc_trait! { /// Parity-bitcoin network interface pub trait Network { /// 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", "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", "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", "onetry"], "id":1 }' -H 'content-type: application/json' http://127.0.0.1:8332/ #[rpc(name = "addnode")] fn add_node(&self, String, AddNodeOperation) -> Result<(), Error>; /// 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, "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] }' -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")] fn node_info(&self, bool, Trailing) -> Result, Error>; /// 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")] fn connection_count(&self) -> Result; } diff --git a/rpc/src/v1/traits/raw.rs b/rpc/src/v1/traits/raw.rs index 5dac5e26..2318fadb 100644 --- a/rpc/src/v1/traits/raw.rs +++ b/rpc/src/v1/traits/raw.rs @@ -9,22 +9,22 @@ use v1::types::TransactionOutputs; use v1::types::GetRawTransactionResponse; build_rpc_trait! { - /// Partiy-bitcoin raw data interface. + /// Parity-bitcoin raw data interface. pub trait Raw { /// 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")] fn send_raw_transaction(&self, RawTransaction) -> Result; /// 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")] fn create_raw_transaction(&self, Vec, TransactionOutputs, Trailing) -> Result; /// 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")] fn decode_raw_transaction(&self, RawTransaction) -> Result; /// 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")] fn get_raw_transaction(&self, H256, Trailing) -> Result; } From 11de03ed6b7308e830988cea53a62d8194765ede Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 31 Aug 2017 16:14:26 +0200 Subject: [PATCH 5/8] List APIs and default ports in CLI help. --- pbtc/cli.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pbtc/cli.yml b/pbtc/cli.yml index b62ce6fd..0bf9d2a2 100644 --- a/pbtc/cli.yml +++ b/pbtc/cli.yml @@ -30,7 +30,7 @@ args: - port: long: port value_name: PORT - help: Listen for connections on PORT + help: Listen for connections on PORT, default 8333. takes_value: true - print-to-console: long: print-to-console @@ -56,7 +56,7 @@ args: help: Disable the JSON-RPC API server - jsonrpc-port: long: jsonrpc-port - help: The port portion of the JSONRPC API server + help: The port portion of the JSONRPC API server, default 8332. takes_value: true value_name: PORT - jsonrpc-interface: @@ -71,7 +71,7 @@ args: value_name: URL - jsonrpc-apis: long: jsonrpc-apis - help: Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. + 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 value_name: APIS - jsonrpc-hosts: @@ -106,4 +106,4 @@ subcommands: args: - BLOCK: required: true - help: Either block hash, or block number + help: Either block hash, or block number From f268256e84ff0d0b240eba867020de4e6fea0fe1 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 31 Aug 2017 16:14:58 +0200 Subject: [PATCH 6/8] Add preliminary JSONRPC description to the README. --- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 56e38c4e..2a1909f7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # parity-bitcoin + The Parity Bitcoin client [![Build Status][travis-image]][travis-url] [![Snap Status](https://build.snapcraft.io/badge/paritytech/parity-bitcoin.svg)](https://build.snapcraft.io/user/paritytech/parity-bitcoin) @@ -190,13 +191,13 @@ OPTIONS: -c, --connect Connect only to the specified node -d, --data-dir Specify the database & configuration directory PATH --db-cache Sets db cache size - --jsonrpc-apis Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. + --jsonrpc-apis Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. Available APIs are blockchain, network, miner, raw. --jsonrpc-cors Specify CORS header for JSON-RPC API responses --jsonrpc-hosts List of allowed Host header values --jsonrpc-interface The hostname portion of the JSONRPC API server - --jsonrpc-port The port portion of the JSONRPC API server + --jsonrpc-port The port portion of the JSONRPC API server, default 8332. --only-net Only connect to nodes in network (ipv4 or ipv6) - --port Listen for connections on PORT + --port Listen for connections on PORT, default 8333. -s, --seednode Connect to a node to retrieve peer addresses, and disconnect SUBCOMMANDS: @@ -206,7 +207,124 @@ SUBCOMMANDS: ## 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 From 0635d694492320a17f7f8f8f0be906b2b119d937 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 31 Aug 2017 16:32:43 +0200 Subject: [PATCH 7/8] Remove default ports --- pbtc/cli.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pbtc/cli.yml b/pbtc/cli.yml index 0bf9d2a2..513b02da 100644 --- a/pbtc/cli.yml +++ b/pbtc/cli.yml @@ -30,7 +30,7 @@ args: - port: long: port value_name: PORT - help: Listen for connections on PORT, default 8333. + help: Listen for connections on PORT takes_value: true - print-to-console: long: print-to-console @@ -56,7 +56,7 @@ args: help: Disable the JSON-RPC API server - jsonrpc-port: long: jsonrpc-port - help: The port portion of the JSONRPC API server, default 8332. + help: The port portion of the JSONRPC API server takes_value: true value_name: PORT - jsonrpc-interface: From 3e184138a39ddf17067b21ea8f7632454db4b755 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 31 Aug 2017 16:34:09 +0200 Subject: [PATCH 8/8] Remove default ports --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2a1909f7..8a00023f 100644 --- a/README.md +++ b/README.md @@ -195,9 +195,9 @@ OPTIONS: --jsonrpc-cors Specify CORS header for JSON-RPC API responses --jsonrpc-hosts List of allowed Host header values --jsonrpc-interface The hostname portion of the JSONRPC API server - --jsonrpc-port The port portion of the JSONRPC API server, default 8332. + --jsonrpc-port The port portion of the JSONRPC API server --only-net Only connect to nodes in network (ipv4 or ipv6) - --port Listen for connections on PORT, default 8333. + --port Listen for connections on PORT -s, --seednode Connect to a node to retrieve peer addresses, and disconnect SUBCOMMANDS: