Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release version v0.4.0 #36

Merged
merged 4 commits into from Apr 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
@@ -1,4 +1,15 @@

# v0.4.0

- add RawTx trait for commands that take raw transactions
- update jsonrpc dependency to v0.11.0
- fix for create_raw_transaction
- fix for send_to_address
- fix for get_new_address
- fix for get_tx_out
- fix for get_raw_transaction_verbose
- use `secp256k1::SecretKey` type in API

# v0.3.0

- removed the GetTransaction and GetScript traits
Expand Down
4 changes: 2 additions & 2 deletions client/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "bitcoincore-rpc"
version = "0.3.0"
version = "0.4.0"
authors = [
"Steven Roose <steven@stevenroose.org>",
"Jean Pierre Dudey <jeandudey@hotmail.com>",
Expand All @@ -18,7 +18,7 @@ name = "bitcoincore_rpc"
path = "src/lib.rs"

[dependencies]
bitcoincore-rpc-json = { version = "0.3.0", path = "../json" }
bitcoincore-rpc-json = { version = "0.4.0", path = "../json" }

log = "0.4.5"
jsonrpc = "0.11"
Expand Down
85 changes: 66 additions & 19 deletions client/src/client.rs
Expand Up @@ -13,9 +13,9 @@ use std::result;
use bitcoin;
use hex;
use jsonrpc;
use secp256k1;
use serde;
use serde_json;
use secp256k1;

use bitcoin::{Address, Block, BlockHeader, Transaction};
use bitcoin_amount::Amount;
Expand All @@ -41,11 +41,6 @@ where
Ok(serde_json::to_value(val)?)
}

/// Shorthand for converting bytes into a serde_json::Value.
fn into_json_hex<T: AsRef<[u8]>>(val: T) -> Result<serde_json::Value> {
Ok(serde_json::to_value(hex::encode(val))?)
}

/// Shorthand for converting an Option into an Option<serde_json::Value>.
fn opt_into_json<T>(opt: Option<T>) -> Result<serde_json::Value>
where
Expand Down Expand Up @@ -121,6 +116,41 @@ fn opt_result<T: for<'a> serde::de::Deserialize<'a>>(
}
}

/// Used to pass raw txs into the API.
pub trait RawTx: Sized {
fn raw_hex(self) -> String;
}

impl<'a> RawTx for &'a Transaction {
fn raw_hex(self) -> String {
hex::encode(bitcoin::consensus::encode::serialize(self))
}
}

impl<'a> RawTx for &'a [u8] {
fn raw_hex(self) -> String {
hex::encode(self)
}
}

impl<'a> RawTx for &'a Vec<u8> {
fn raw_hex(self) -> String {
hex::encode(self)
}
}

impl<'a> RawTx for &'a str {
fn raw_hex(self) -> String {
self.to_owned()
}
}

impl RawTx for String {
fn raw_hex(self) -> String {
self
}
}

pub trait RpcApi: Sized {
/// Call a `cmd` rpc with given `args` list
fn call<T: for<'a> serde::de::Deserialize<'a>>(
Expand Down Expand Up @@ -354,15 +384,15 @@ pub trait RpcApi: Sized {
Ok(bitcoin::consensus::encode::deserialize(&bytes)?)
}

fn sign_raw_transaction<B: AsRef<[u8]>>(
fn sign_raw_transaction<R: RawTx>(
&self,
tx: B,
tx: R,
utxos: Option<&[json::SignRawTransactionInput]>,
private_keys: Option<&[&str]>,
sighash_type: Option<json::SigHashType>,
) -> Result<json::SignRawTransactionResult> {
let mut args = [
into_json_hex(tx)?,
tx.raw_hex().into(),
opt_into_json(utxos)?,
opt_into_json(private_keys)?,
opt_into_json(sighash_type)?,
Expand All @@ -375,15 +405,15 @@ pub trait RpcApi: Sized {
self.call("signrawtransaction", handle_defaults(&mut args, &defaults))
}

fn sign_raw_transaction_with_key<B: AsRef<[u8]>>(
fn sign_raw_transaction_with_key<R: RawTx>(
&self,
tx: B,
tx: R,
privkeys: &[&str],
prevtxs: Option<&[json::SignRawTransactionInput]>,
sighash_type: Option<json::SigHashType>,
) -> Result<json::SignRawTransactionResult> {
let mut args = [
into_json_hex(tx)?,
tx.raw_hex().into(),
into_json(privkeys)?,
opt_into_json(prevtxs)?,
opt_into_json(sighash_type)?,
Expand All @@ -400,13 +430,13 @@ pub trait RpcApi: Sized {
self.call("stop", &[])
}

fn sign_raw_transaction_with_wallet<B: AsRef<[u8]>>(
fn sign_raw_transaction_with_wallet<R: RawTx>(
&self,
tx: B,
tx: R,
utxos: Option<&[json::SignRawTransactionInput]>,
sighash_type: Option<json::SigHashType>,
) -> Result<json::SignRawTransactionResult> {
let mut args = [into_json_hex(tx)?, opt_into_json(utxos)?, opt_into_json(sighash_type)?];
let mut args = [tx.raw_hex().into(), opt_into_json(utxos)?, opt_into_json(sighash_type)?];
let defaults = [into_json::<&[json::SignRawTransactionInput]>(&[])?, null()];
self.call("signrawtransactionwithwallet", handle_defaults(&mut args, &defaults))
}
Expand Down Expand Up @@ -492,8 +522,8 @@ pub trait RpcApi: Sized {
self.call("ping", &[])
}

fn send_raw_transaction(&self, tx: &str) -> Result<String> {
self.call("sendrawtransaction", &[into_json(tx)?])
fn send_raw_transaction<R: RawTx>(&self, tx: R) -> Result<sha256d::Hash> {
self.call("sendrawtransaction", &[tx.raw_hex().into()])
}

fn estimate_smartfee<E>(
Expand Down Expand Up @@ -574,13 +604,25 @@ impl RpcApi for Client {
}
}

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

#[test]
fn test_handle_defaults() -> Result<()> {
fn test_raw_tx() {
use bitcoin::consensus::encode;
let client = Client::new("http://localhost/".into(), None, None);
let tx: bitcoin::Transaction = encode::deserialize(&hex::decode("0200000001586bd02815cf5faabfec986a4e50d25dbee089bd2758621e61c5fab06c334af0000000006b483045022100e85425f6d7c589972ee061413bcf08dc8c8e589ce37b217535a42af924f0e4d602205c9ba9cb14ef15513c9d946fa1c4b797883e748e8c32171bdf6166583946e35c012103dae30a4d7870cd87b45dd53e6012f71318fdd059c1c2623b8cc73f8af287bb2dfeffffff021dc4260c010000001976a914f602e88b2b5901d8aab15ebe4a97cf92ec6e03b388ac00e1f505000000001976a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88acfd211500").unwrap()).unwrap();

assert!(client.send_raw_transaction(&tx).is_err());
assert!(client.send_raw_transaction(&encode::serialize(&tx)).is_err());
assert!(client.send_raw_transaction("deadbeef").is_err());
assert!(client.send_raw_transaction("deadbeef".to_owned()).is_err());
}

fn test_handle_defaults_inner() -> Result<()> {
{
let mut args = [into_json(0)?, null(), null()];
let defaults = [into_json(1)?, into_json(2)?];
Expand Down Expand Up @@ -631,4 +673,9 @@ mod tests {
}
Ok(())
}

#[test]
fn test_handle_defaults() {
test_handle_defaults_inner().unwrap();
}
}
2 changes: 1 addition & 1 deletion json/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "bitcoincore-rpc-json"
version = "0.3.0"
version = "0.4.0"
authors = [
"Steven Roose <steven@stevenroose.org>",
"Jean Pierre Dudey <jeandudey@hotmail.com>",
Expand Down
24 changes: 12 additions & 12 deletions json/src/lib.rs
Expand Up @@ -195,10 +195,10 @@ pub struct GetRawTransactionResultVoutScriptPubKey {
pub asm: String,
#[serde(with = "::serde_hex")]
pub hex: Vec<u8>,
pub req_sigs: usize,
pub req_sigs: Option<usize>,
#[serde(rename = "type")]
pub type_: String, //TODO(stevenroose) consider enum
pub addresses: Vec<Address>,
pub type_: Option<String>, //TODO(stevenroose) consider enum
pub addresses: Option<Vec<Address>>,
}

impl GetRawTransactionResultVoutScriptPubKey {
Expand Down Expand Up @@ -868,19 +868,19 @@ mod tests {
script_pub_key: GetRawTransactionResultVoutScriptPubKey{
asm: "OP_DUP OP_HASH160 f602e88b2b5901d8aab15ebe4a97cf92ec6e03b3 OP_EQUALVERIFY OP_CHECKSIG".into(),
hex: hex!("76a914f602e88b2b5901d8aab15ebe4a97cf92ec6e03b388ac"),
req_sigs: 1,
type_: "pubkeyhash".into(),
addresses: vec![addr!("n3wk1KcFnVibGdqQa6jbwoR8gbVtRbYM4M")],
req_sigs: Some(1),
type_: Some("pubkeyhash".into()),
addresses: Some(vec![addr!("n3wk1KcFnVibGdqQa6jbwoR8gbVtRbYM4M")]),
},
}, GetRawTransactionResultVout{
value: Amount::from_btc(1.0),
n: 1,
script_pub_key: GetRawTransactionResultVoutScriptPubKey{
asm: "OP_DUP OP_HASH160 687ffeffe8cf4e4c038da46a9b1d37db385a472d OP_EQUALVERIFY OP_CHECKSIG".into(),
hex: hex!("76a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88ac"),
req_sigs: 1,
type_: "pubkeyhash".into(),
addresses: vec![addr!("mq3VuL2K63VKWkp8vvqRiJPre4h9awrHfA")],
req_sigs: Some(1),
type_: Some("pubkeyhash".into()),
addresses: Some(vec![addr!("mq3VuL2K63VKWkp8vvqRiJPre4h9awrHfA")]),
},
}],
blockhash: Some(hash!("00000000000000039dc06adbd7666a8d1df9acf9d0329d73651b764167d63765")),
Expand Down Expand Up @@ -1017,9 +1017,9 @@ mod tests {
script_pub_key: GetRawTransactionResultVoutScriptPubKey{
asm: "OP_DUP OP_HASH160 687ffeffe8cf4e4c038da46a9b1d37db385a472d OP_EQUALVERIFY OP_CHECKSIG".into(),
hex: hex!("76a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88ac"),
req_sigs: 1,
type_: "pubkeyhash".into(),
addresses: vec![addr!("mq3VuL2K63VKWkp8vvqRiJPre4h9awrHfA")],
req_sigs: Some(1),
type_: Some("pubkeyhash".into()),
addresses: Some(vec![addr!("mq3VuL2K63VKWkp8vvqRiJPre4h9awrHfA")]),
},
coinbase: false,
};
Expand Down