Skip to content

Commit 066849a

Browse files
committed
Add generate block command
1 parent bde02d7 commit 066849a

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

client/src/client.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use serde_json;
2222
use crate::bitcoin::hashes::hex::{FromHex, ToHex};
2323
use crate::bitcoin::secp256k1::ecdsa::Signature;
2424
use crate::bitcoin::{
25-
Address, Amount, Block, BlockHeader, OutPoint, PrivateKey, PublicKey, Script, Transaction,
25+
Address, Amount, Block, BlockHeader, OutPoint, PrivateKey, PublicKey, Script, Transaction, Txid,
2626
};
2727
use log::Level::{Debug, Trace, Warn};
2828

@@ -186,6 +186,13 @@ impl RawTx for String {
186186
}
187187
}
188188

189+
/// The different authentication methods for the client.
190+
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
191+
pub enum MineableTx {
192+
RawTx(Transaction),
193+
Txid(Txid),
194+
}
195+
189196
/// The different authentication methods for the client.
190197
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
191198
pub enum Auth {
@@ -866,6 +873,23 @@ pub trait RpcApi: Sized {
866873
self.call("generate", &[block_num.into(), opt_into_json(maxtries)?])
867874
}
868875

876+
/// Mine a set of ordered transactions to a specified address
877+
/// and return the block hash.
878+
fn generate_block(
879+
&self,
880+
address: &Address,
881+
txs: &[MineableTx],
882+
) -> Result<json::GenerateBlockResult> {
883+
let tx_strs: Vec<_> = txs
884+
.iter()
885+
.map(|t| match t.to_owned() {
886+
MineableTx::RawTx(tx) => tx.raw_hex(),
887+
MineableTx::Txid(txid) => txid.to_hex(),
888+
})
889+
.collect();
890+
self.call("generateblock", &[address.to_string().into(), tx_strs.into()])
891+
}
892+
869893
/// Mark a block as invalid by `block_hash`
870894
fn invalidate_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
871895
self.call("invalidateblock", &[into_json(block_hash)?])

integration_test/src/main.rs

+50
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ fn main() {
140140
test_generate(&cl);
141141
test_get_balance_generate_to_address(&cl);
142142
test_get_balances_generate_to_address(&cl);
143+
test_generate_block(&cl);
143144
test_get_best_block_hash(&cl);
144145
test_get_block_count(&cl);
145146
test_get_block_hash(&cl);
@@ -277,6 +278,55 @@ fn test_get_balances_generate_to_address(cl: &Client) {
277278
}
278279
}
279280

281+
fn test_generate_block(cl: &Client) {
282+
let sk = PrivateKey {
283+
network: Network::Regtest,
284+
inner: secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()),
285+
compressed: true,
286+
};
287+
let addr = Address::p2wpkh(&sk.public_key(&SECP), Network::Regtest).unwrap();
288+
289+
let options = json::ListUnspentQueryOptions {
290+
minimum_amount: Some(btc(2)),
291+
..Default::default()
292+
};
293+
let unspent = cl.list_unspent(Some(6), None, None, None, Some(options)).unwrap();
294+
let unspent = unspent.into_iter().nth(0).unwrap();
295+
296+
let tx = Transaction {
297+
version: 1,
298+
lock_time: PackedLockTime::ZERO,
299+
input: vec![TxIn {
300+
previous_output: OutPoint {
301+
txid: unspent.txid,
302+
vout: unspent.vout,
303+
},
304+
sequence: Sequence::MAX,
305+
script_sig: Script::new(),
306+
witness: Witness::new(),
307+
}],
308+
output: vec![TxOut {
309+
value: (unspent.amount - *FEE).to_sat(),
310+
script_pubkey: addr.script_pubkey(),
311+
}],
312+
};
313+
314+
let input = json::SignRawTransactionInput {
315+
txid: unspent.txid,
316+
vout: unspent.vout,
317+
script_pub_key: unspent.script_pub_key,
318+
redeem_script: None,
319+
amount: Some(unspent.amount),
320+
};
321+
let res = cl.sign_raw_transaction_with_wallet(&tx, Some(&[input]), None).unwrap();
322+
assert!(res.complete);
323+
324+
let raw_tx = bitcoincore_rpc::MineableTx::RawTx(res.transaction().unwrap());
325+
let result = cl.generate_block(&cl.get_new_address(None, None).unwrap(), &[raw_tx]).unwrap();
326+
let tip = cl.get_best_block_hash().unwrap();
327+
assert_eq!(result.hash, tip);
328+
}
329+
280330
fn test_get_best_block_hash(cl: &Client) {
281331
let _ = cl.get_best_block_hash().unwrap();
282332
}

json/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,13 @@ pub struct GetAddressInfoResult {
988988
pub label: Option<String>,
989989
}
990990

991+
/// Models the result of "generateblock"
992+
#[derive(Clone, Debug, Deserialize, Serialize)]
993+
pub struct GenerateBlockResult {
994+
/// Hash of the block generated
995+
pub hash: bitcoin::BlockHash,
996+
}
997+
991998
/// Models the result of "getblockchaininfo"
992999
#[derive(Clone, Debug, Deserialize, Serialize)]
9931000
pub struct GetBlockchainInfoResult {

0 commit comments

Comments
 (0)