Skip to content

Commit 1520b83

Browse files
authored
Merge pull request #163 from 0xB10C/2021-02-getblocktemplate
add: support for getblocktemplate in template mode
2 parents 200fc82 + 3106381 commit 1520b83

File tree

3 files changed

+233
-1
lines changed

3 files changed

+233
-1
lines changed

Diff for: client/src/client.rs

+23
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,29 @@ pub trait RpcApi: Sized {
351351
self.call("getmininginfo", &[])
352352
}
353353

354+
fn get_block_template(
355+
&self,
356+
mode: json::GetBlockTemplateModes,
357+
rules: &[json::GetBlockTemplateRules],
358+
capabilities: &[json::GetBlockTemplateCapabilities],
359+
) -> Result<json::GetBlockTemplateResult> {
360+
#[derive(Serialize)]
361+
struct Argument<'a> {
362+
mode: json::GetBlockTemplateModes,
363+
rules: &'a [json::GetBlockTemplateRules],
364+
capabilities: &'a [json::GetBlockTemplateCapabilities],
365+
}
366+
367+
self.call(
368+
"getblocktemplate",
369+
&[into_json(Argument {
370+
mode: mode,
371+
rules: rules,
372+
capabilities: capabilities,
373+
})?],
374+
)
375+
}
376+
354377
/// Returns a data structure containing various state info regarding
355378
/// blockchain processing.
356379
fn get_blockchain_info(&self) -> Result<json::GetBlockchainInfoResult> {

Diff for: integration_test/src/main.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ use bitcoin::{
3030
Address, Amount, Network, OutPoint, PrivateKey, Script, SigHashType, SignedAmount, Transaction,
3131
TxIn, TxOut, Txid,
3232
};
33-
use bitcoincore_rpc::bitcoincore_rpc_json::ScanTxOutRequest;
33+
use bitcoincore_rpc::bitcoincore_rpc_json::{
34+
GetBlockTemplateModes, GetBlockTemplateRules, ScanTxOutRequest,
35+
};
3436

3537
lazy_static! {
3638
static ref SECP: secp256k1::Secp256k1<secp256k1::All> = secp256k1::Secp256k1::new();
@@ -188,6 +190,7 @@ fn main() {
188190
test_get_net_totals(&cl);
189191
test_get_network_hash_ps(&cl);
190192
test_uptime(&cl);
193+
test_getblocktemplate(&cl);
191194
//TODO import_multi(
192195
//TODO verify_message(
193196
//TODO wait_for_new_block(&self, timeout: u64) -> Result<json::BlockRef> {
@@ -1030,6 +1033,20 @@ fn test_scantxoutset(cl: &Client) {
10301033
assert_eq!(utxos.success, Some(true));
10311034
}
10321035

1036+
fn test_getblocktemplate(cl: &Client) {
1037+
// We want to have a transaction in the mempool so the GetBlockTemplateResult
1038+
// contains an entry in the vector of GetBlockTemplateResultTransaction.
1039+
// Otherwise the GetBlockTemplateResultTransaction deserialization wouldn't
1040+
// be tested.
1041+
cl.send_to_address(&RANDOM_ADDRESS, btc(1), None, None, None, None, None, None).unwrap();
1042+
1043+
cl.get_block_template(GetBlockTemplateModes::Template, &[GetBlockTemplateRules::SegWit], &[])
1044+
.unwrap();
1045+
1046+
// cleanup mempool transaction
1047+
cl.generate_to_address(2, &RANDOM_ADDRESS).unwrap();
1048+
}
1049+
10331050
fn test_stop(cl: Client) {
10341051
println!("Stopping: '{}'", cl.stop().unwrap());
10351052
}

Diff for: json/src/lib.rs

+192
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,198 @@ pub struct GetDescriptorInfoResult {
11231123
pub has_private_keys: bool,
11241124
}
11251125

1126+
/// Models the request options of "getblocktemplate"
1127+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1128+
pub struct GetBlockTemplateOptions {
1129+
pub mode: GetBlockTemplateModes,
1130+
//// List of client side supported softfork deployment
1131+
pub rules: Vec<GetBlockTemplateRules>,
1132+
/// List of client side supported features
1133+
pub capabilities: Vec<GetBlockTemplateCapabilities>,
1134+
}
1135+
1136+
/// Enum to represent client-side supported features
1137+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1138+
#[serde(rename_all = "lowercase")]
1139+
pub enum GetBlockTemplateCapabilities {
1140+
// No features supported yet. In the future this could be, for example, Proposal and Longpolling
1141+
}
1142+
1143+
/// Enum to representing specific block rules that the requested template
1144+
/// should support.
1145+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1146+
#[serde(rename_all = "lowercase")]
1147+
pub enum GetBlockTemplateRules {
1148+
SegWit,
1149+
Signet,
1150+
Csv,
1151+
Taproot,
1152+
}
1153+
1154+
/// Enum to represent client-side supported features.
1155+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1156+
#[serde(rename_all = "lowercase")]
1157+
pub enum GetBlockTemplateModes {
1158+
/// Using this mode, the server build a block template and return it as
1159+
/// response to the request. This is the default mode.
1160+
Template,
1161+
// TODO: Support for "proposal" mode is not yet implemented on the client
1162+
// side.
1163+
}
1164+
1165+
/// Models the result of "getblocktemplate"
1166+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1167+
pub struct GetBlockTemplateResult {
1168+
/// The compressed difficulty in hexadecimal
1169+
#[serde(with = "::serde_hex")]
1170+
pub bits: Vec<u8>,
1171+
/// The previous block hash the current template is mining on
1172+
#[serde(rename = "previousblockhash")]
1173+
pub previous_block_hash: bitcoin::BlockHash,
1174+
/// The current time as seen by the server (recommended for block time)
1175+
/// Note: this is not necessarily the system clock, and must fall within
1176+
/// the mintime/maxtime rules. Expressed as UNIX timestamp.
1177+
#[serde(rename = "curtime")]
1178+
pub current_time: u64,
1179+
/// The height of the block we will be mining: `current height + 1`
1180+
pub height: u64,
1181+
/// Block sigops limit
1182+
#[serde(rename = "sigoplimit")]
1183+
pub sigop_limit: u32,
1184+
/// Block size limit
1185+
#[serde(rename = "sizelimit")]
1186+
pub size_limit: u32,
1187+
/// Block weight limit
1188+
#[serde(rename = "weightlimit")]
1189+
pub weight_limit: u32,
1190+
/// Block header version
1191+
pub version: u32,
1192+
/// Block rules that are to be enforced
1193+
pub rules: Vec<GetBlockTemplateResultRules>,
1194+
/// List of features the Bitcoin Core getblocktemplate implementation supports
1195+
pub capabilities: Vec<GetBlockTemplateResultCapabilities>,
1196+
/// Set of pending, supported versionbit (BIP 9) softfork deployments
1197+
#[serde(rename = "vbavailable")]
1198+
pub version_bits_available: HashMap<u32, String>,
1199+
/// Bit mask of versionbits the server requires set in submissions
1200+
#[serde(rename = "vbrequired")]
1201+
pub version_bits_required: u32,
1202+
/// Id used in longpoll requests for this template.
1203+
pub longpollid: String,
1204+
/// List of transactions included in the template block
1205+
pub transactions: Vec<GetBlockTemplateResultTransaction>,
1206+
/// The signet challenge. Only set if mining on a signet, otherwise empty
1207+
#[serde(default, with = "bitcoin::blockdata::script::Script")]
1208+
pub signet_challenge: bitcoin::blockdata::script::Script,
1209+
/// The default witness commitment included in an OP_RETURN output of the
1210+
/// coinbase transactions. Only set when mining on a network where SegWit
1211+
/// is activated.
1212+
#[serde(with = "bitcoin::blockdata::script::Script", default)]
1213+
pub default_witness_commitment: bitcoin::blockdata::script::Script,
1214+
/// Data that should be included in the coinbase's scriptSig content. Only
1215+
/// the values (hexadecimal byte-for-byte) in this map should be included,
1216+
/// not the keys. This does not include the block height, which is required
1217+
/// to be included in the scriptSig by BIP 0034. It is advisable to encode
1218+
/// values inside "PUSH" opcodes, so as to not inadvertently expend SIGOPs
1219+
/// (which are counted toward limits, despite not being executed).
1220+
pub coinbaseaux: HashMap<String, String>,
1221+
/// Total funds available for the coinbase
1222+
#[serde(rename = "coinbasevalue", with = "bitcoin::util::amount::serde::as_sat", default)]
1223+
pub coinbase_value: Amount,
1224+
/// The number which valid hashes must be less than, in big-endian
1225+
#[serde(with = "::serde_hex")]
1226+
pub target: Vec<u8>,
1227+
/// The minimum timestamp appropriate for the next block time. Expressed as
1228+
/// UNIX timestamp.
1229+
#[serde(rename = "mintime")]
1230+
pub min_time: u64,
1231+
/// List of things that may be changed by the client before submitting a
1232+
/// block
1233+
pub mutable: Vec<GetBlockTemplateResulMutations>,
1234+
/// A range of valid nonces
1235+
#[serde(with = "::serde_hex", rename = "noncerange")]
1236+
pub nonce_range: Vec<u8>,
1237+
}
1238+
1239+
/// Models a single transaction entry in the result of "getblocktemplate"
1240+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1241+
pub struct GetBlockTemplateResultTransaction {
1242+
/// The transaction id
1243+
pub txid: bitcoin::Txid,
1244+
/// The wtxid of the transaction
1245+
#[serde(rename = "hash")]
1246+
pub wtxid: bitcoin::Wtxid,
1247+
/// The serilaized transaction bytes
1248+
#[serde(with = "::serde_hex", rename = "data")]
1249+
pub raw_tx: Vec<u8>,
1250+
// The transaction fee
1251+
#[serde(with = "bitcoin::util::amount::serde::as_sat")]
1252+
pub fee: Amount,
1253+
/// Transaction sigops
1254+
pub sigops: u32,
1255+
/// Transaction weight in weight units
1256+
pub weight: usize,
1257+
/// Transactions that must be in present in the final block if this one is.
1258+
/// Indexed by a 1-based index in the `GetBlockTemplateResult.transactions`
1259+
/// list
1260+
pub depends: Vec<u32>,
1261+
}
1262+
1263+
impl GetBlockTemplateResultTransaction {
1264+
pub fn transaction(&self) -> Result<Transaction, encode::Error> {
1265+
encode::deserialize(&self.raw_tx)
1266+
}
1267+
}
1268+
1269+
/// Enum to represent Bitcoin Core's supported features for getblocktemplate
1270+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1271+
#[serde(rename_all = "lowercase")]
1272+
pub enum GetBlockTemplateResultCapabilities {
1273+
Proposal,
1274+
}
1275+
1276+
/// Enum to representing specific block rules that client must support to work
1277+
/// with the template returned by Bitcoin Core
1278+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1279+
#[serde(rename_all = "lowercase")]
1280+
pub enum GetBlockTemplateResultRules {
1281+
/// Inidcates that the client must support the SegWit rules when using this
1282+
/// template.
1283+
#[serde(alias = "!segwit")]
1284+
SegWit,
1285+
/// Indicates that the client must support the Signet rules when using this
1286+
/// template.
1287+
#[serde(alias = "!signet")]
1288+
Signet,
1289+
/// Indicates that the client must support the CSV rules when using this
1290+
/// template.
1291+
Csv,
1292+
/// Indicates that the client must support the taproot rules when using this
1293+
/// template.
1294+
Taproot,
1295+
/// Indicates that the client must support the Regtest rules when using this
1296+
/// template. TestDummy is a test soft-fork only used on the regtest network.
1297+
Testdummy,
1298+
}
1299+
1300+
/// Enum to representing mutable parts of the block template. This does only
1301+
/// cover the muations implemented in Bitcoin Core. More mutations are defined
1302+
/// in [BIP-23](https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki#Mutations),
1303+
/// but not implemented in the getblocktemplate implementation of Bitcoin Core.
1304+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1305+
#[serde(rename_all = "lowercase")]
1306+
pub enum GetBlockTemplateResulMutations {
1307+
/// The client is allowed to modify the time in the header of the block
1308+
Time,
1309+
/// The client is allowed to add transactions to the block
1310+
Transactions,
1311+
/// The client is allowed to use the work with other previous blocks.
1312+
/// This implicitly allows removing transactions that are no longer valid.
1313+
/// It also implies adjusting the "height" as necessary.
1314+
#[serde(rename = "prevblock")]
1315+
PreviousBlock,
1316+
}
1317+
11261318
/// Models the result of "walletcreatefundedpsbt"
11271319
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
11281320
pub struct WalletCreateFundedPsbtResult {

0 commit comments

Comments
 (0)