Skip to content

Commit 9dfddde

Browse files
authoredMar 25, 2025··
fix(rpc): getblocktemplate coinbase outputs order (#9272)
* change the output order in getblocktemplate zcashd mode * add a test for coinbase output order * update snapshots
1 parent 979cdaf commit 9dfddde

10 files changed

+72
-44
lines changed
 

‎zebra-rpc/src/methods/get_block_template_rpcs/get_block_template.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -394,24 +394,34 @@ fn combine_coinbase_outputs(
394394
miner_reward: Amount<NonNegative>,
395395
like_zcashd: bool,
396396
) -> Vec<(Amount<NonNegative>, transparent::Script)> {
397-
// Combine all the funding streams with the miner reward.
398-
let mut coinbase_outputs: Vec<(Amount<NonNegative>, &transparent::Address)> = funding_streams
399-
.into_iter()
400-
.map(|(_receiver, (amount, address))| (amount, address))
401-
.collect();
402-
coinbase_outputs.push((miner_reward, miner_address));
403-
404-
let mut coinbase_outputs: Vec<(Amount<NonNegative>, transparent::Script)> = coinbase_outputs
405-
.iter()
406-
.map(|(amount, address)| (*amount, address.create_script_from_address()))
407-
.collect();
397+
// Collect all the funding streams and convert them to outputs.
398+
let funding_streams_outputs: Vec<(Amount<NonNegative>, &transparent::Address)> =
399+
funding_streams
400+
.into_iter()
401+
.map(|(_receiver, (amount, address))| (amount, address))
402+
.collect();
403+
404+
let mut coinbase_outputs: Vec<(Amount<NonNegative>, transparent::Script)> =
405+
funding_streams_outputs
406+
.iter()
407+
.map(|(amount, address)| (*amount, address.create_script_from_address()))
408+
.collect();
408409

409410
// The HashMap returns funding streams in an arbitrary order,
410411
// but Zebra's snapshot tests expect the same order every time.
411412
if like_zcashd {
412413
// zcashd sorts outputs in serialized data order, excluding the length field
413414
coinbase_outputs.sort_by_key(|(_amount, script)| script.clone());
415+
416+
// The miner reward is always the first output independent of the sort order
417+
coinbase_outputs.insert(
418+
0,
419+
(miner_reward, miner_address.create_script_from_address()),
420+
);
414421
} else {
422+
// Unlike zcashd, in Zebra the miner reward is part of the sorting
423+
coinbase_outputs.push((miner_reward, miner_address.create_script_from_address()));
424+
415425
// Zebra sorts by amount then script.
416426
//
417427
// Since the sort is stable, equal amounts will remain sorted by script.

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_basic.coinbase_tx@mainnet_10.snap

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ V4(
1313
),
1414
],
1515
outputs: [
16+
Output(
17+
value: 250000000,
18+
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
19+
),
1620
Output(
1721
value: 21875000,
1822
lock_script: Script("a91469a9f95a98fe581b6eb52841ef4806dc4402eb9087"),
@@ -21,10 +25,6 @@ V4(
2125
value: 25000000,
2226
lock_script: Script("a914931fec54c1fea86e574462cc32013f5400b8912987"),
2327
),
24-
Output(
25-
value: 250000000,
26-
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
27-
),
2828
Output(
2929
value: 15625000,
3030
lock_script: Script("a914d45cb1adffb5215a42720532a076f02c7c778c9087"),

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_basic.coinbase_tx@testnet_10.snap

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ V4(
1313
),
1414
],
1515
outputs: [
16+
Output(
17+
value: 250000000,
18+
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
19+
),
1620
Output(
1721
value: 15625000,
1822
lock_script: Script("a9140c0bcca02f3cba01a5d7423ac3903d40586399eb87"),
@@ -25,10 +29,6 @@ V4(
2529
value: 25000000,
2630
lock_script: Script("a91471e1df05024288a00802de81e08c437859586c8787"),
2731
),
28-
Output(
29-
value: 250000000,
30-
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
31-
),
3232
],
3333
lock_time: Height(Height(0)),
3434
expiry_height: Height(1842421),

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_basic@mainnet_10.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ expression: block_template
1212
"lightclientroothash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a",
1313
"finalsaplingroothash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a",
1414
"defaultroots": {
15-
"merkleroot": "e049ed10466f566a045702ad712bbb596c6863cd08cdb4646da749b2287bc219",
15+
"merkleroot": "7df8ce149b9beafc09b649c2ccfd866ce96d1b94331d9f7f3728cbefa36431f6",
1616
"chainhistoryroot": "94470fa66ebd1a5fdb109a5aa3f3204f14de3a42135e71aa7f4c44055847e0b5",
1717
"authdataroot": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1818
"blockcommitmentshash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a"
1919
},
2020
"transactions": [],
2121
"coinbasetxn": {
22-
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff050341be1900ffffffff0438c94d010000000017a91469a9f95a98fe581b6eb52841ef4806dc4402eb908740787d010000000017a914931fec54c1fea86e574462cc32013f5400b891298780b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad87286bee000000000017a914d45cb1adffb5215a42720532a076f02c7c778c90870000000041be19000000000000000000000000",
23-
"hash": "e049ed10466f566a045702ad712bbb596c6863cd08cdb4646da749b2287bc219",
22+
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff050341be1900ffffffff0480b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad8738c94d010000000017a91469a9f95a98fe581b6eb52841ef4806dc4402eb908740787d010000000017a914931fec54c1fea86e574462cc32013f5400b8912987286bee000000000017a914d45cb1adffb5215a42720532a076f02c7c778c90870000000041be19000000000000000000000000",
23+
"hash": "7df8ce149b9beafc09b649c2ccfd866ce96d1b94331d9f7f3728cbefa36431f6",
2424
"authdigest": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2525
"depends": [],
2626
"fee": 0,

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_basic@testnet_10.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ expression: block_template
1212
"lightclientroothash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792",
1313
"finalsaplingroothash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792",
1414
"defaultroots": {
15-
"merkleroot": "f1f2db76c33c4a81f799d0c5cfba83c99c20cc8c51958a615d410fe7fbf92b34",
15+
"merkleroot": "e919e7a3325b82b571b3658408118c14f2688ea254f9cb54d354a8ff17bd5b81",
1616
"chainhistoryroot": "03bc75f00c307a05aed2023819e18c2672cbe15fbd3200944997def141967387",
1717
"authdataroot": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1818
"blockcommitmentshash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792"
1919
},
2020
"transactions": [],
2121
"coinbasetxn": {
22-
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0503f51c1c00ffffffff04286bee000000000017a9140c0bcca02f3cba01a5d7423ac3903d40586399eb8738c94d010000000017a9144e3f0d9a33a2721604cbae2de8d9171e21f8fbe48740787d010000000017a91471e1df05024288a00802de81e08c437859586c878780b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad8700000000f51c1c000000000000000000000000",
23-
"hash": "f1f2db76c33c4a81f799d0c5cfba83c99c20cc8c51958a615d410fe7fbf92b34",
22+
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0503f51c1c00ffffffff0480b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad87286bee000000000017a9140c0bcca02f3cba01a5d7423ac3903d40586399eb8738c94d010000000017a9144e3f0d9a33a2721604cbae2de8d9171e21f8fbe48740787d010000000017a91471e1df05024288a00802de81e08c437859586c878700000000f51c1c000000000000000000000000",
23+
"hash": "e919e7a3325b82b571b3658408118c14f2688ea254f9cb54d354a8ff17bd5b81",
2424
"authdigest": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2525
"depends": [],
2626
"fee": 0,

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_long_poll.coinbase_tx@mainnet_10.snap

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ V4(
1313
),
1414
],
1515
outputs: [
16+
Output(
17+
value: 250000000,
18+
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
19+
),
1620
Output(
1721
value: 21875000,
1822
lock_script: Script("a91469a9f95a98fe581b6eb52841ef4806dc4402eb9087"),
@@ -21,10 +25,6 @@ V4(
2125
value: 25000000,
2226
lock_script: Script("a914931fec54c1fea86e574462cc32013f5400b8912987"),
2327
),
24-
Output(
25-
value: 250000000,
26-
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
27-
),
2828
Output(
2929
value: 15625000,
3030
lock_script: Script("a914d45cb1adffb5215a42720532a076f02c7c778c9087"),

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_long_poll.coinbase_tx@testnet_10.snap

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ V4(
1313
),
1414
],
1515
outputs: [
16+
Output(
17+
value: 250000000,
18+
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
19+
),
1620
Output(
1721
value: 15625000,
1822
lock_script: Script("a9140c0bcca02f3cba01a5d7423ac3903d40586399eb87"),
@@ -25,10 +29,6 @@ V4(
2529
value: 25000000,
2630
lock_script: Script("a91471e1df05024288a00802de81e08c437859586c8787"),
2731
),
28-
Output(
29-
value: 250000000,
30-
lock_script: Script("a914adadadadadadadadadadadadadadadadadadadad87"),
31-
),
3232
],
3333
lock_time: Height(Height(0)),
3434
expiry_height: Height(1842421),

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_long_poll@mainnet_10.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ expression: block_template
1212
"lightclientroothash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a",
1313
"finalsaplingroothash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a",
1414
"defaultroots": {
15-
"merkleroot": "e049ed10466f566a045702ad712bbb596c6863cd08cdb4646da749b2287bc219",
15+
"merkleroot": "7df8ce149b9beafc09b649c2ccfd866ce96d1b94331d9f7f3728cbefa36431f6",
1616
"chainhistoryroot": "94470fa66ebd1a5fdb109a5aa3f3204f14de3a42135e71aa7f4c44055847e0b5",
1717
"authdataroot": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1818
"blockcommitmentshash": "02990723c6b62a724651322d141b4a72a4ffd66518167d809badbd5117d5518a"
1919
},
2020
"transactions": [],
2121
"coinbasetxn": {
22-
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff050341be1900ffffffff0438c94d010000000017a91469a9f95a98fe581b6eb52841ef4806dc4402eb908740787d010000000017a914931fec54c1fea86e574462cc32013f5400b891298780b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad87286bee000000000017a914d45cb1adffb5215a42720532a076f02c7c778c90870000000041be19000000000000000000000000",
23-
"hash": "e049ed10466f566a045702ad712bbb596c6863cd08cdb4646da749b2287bc219",
22+
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff050341be1900ffffffff0480b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad8738c94d010000000017a91469a9f95a98fe581b6eb52841ef4806dc4402eb908740787d010000000017a914931fec54c1fea86e574462cc32013f5400b8912987286bee000000000017a914d45cb1adffb5215a42720532a076f02c7c778c90870000000041be19000000000000000000000000",
23+
"hash": "7df8ce149b9beafc09b649c2ccfd866ce96d1b94331d9f7f3728cbefa36431f6",
2424
"authdigest": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2525
"depends": [],
2626
"fee": 0,

‎zebra-rpc/src/methods/tests/snapshot/snapshots/get_block_template_long_poll@testnet_10.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ expression: block_template
1212
"lightclientroothash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792",
1313
"finalsaplingroothash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792",
1414
"defaultroots": {
15-
"merkleroot": "f1f2db76c33c4a81f799d0c5cfba83c99c20cc8c51958a615d410fe7fbf92b34",
15+
"merkleroot": "e919e7a3325b82b571b3658408118c14f2688ea254f9cb54d354a8ff17bd5b81",
1616
"chainhistoryroot": "03bc75f00c307a05aed2023819e18c2672cbe15fbd3200944997def141967387",
1717
"authdataroot": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1818
"blockcommitmentshash": "3b25791957f9383b6ce851d728a78309664d5d7a82ca87b6a9125a2f2c529792"
1919
},
2020
"transactions": [],
2121
"coinbasetxn": {
22-
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0503f51c1c00ffffffff04286bee000000000017a9140c0bcca02f3cba01a5d7423ac3903d40586399eb8738c94d010000000017a9144e3f0d9a33a2721604cbae2de8d9171e21f8fbe48740787d010000000017a91471e1df05024288a00802de81e08c437859586c878780b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad8700000000f51c1c000000000000000000000000",
23-
"hash": "f1f2db76c33c4a81f799d0c5cfba83c99c20cc8c51958a615d410fe7fbf92b34",
22+
"data": "0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0503f51c1c00ffffffff0480b2e60e0000000017a914adadadadadadadadadadadadadadadadadadadad87286bee000000000017a9140c0bcca02f3cba01a5d7423ac3903d40586399eb8738c94d010000000017a9144e3f0d9a33a2721604cbae2de8d9171e21f8fbe48740787d010000000017a91471e1df05024288a00802de81e08c437859586c878700000000f51c1c000000000000000000000000",
23+
"hash": "e919e7a3325b82b571b3658408118c14f2688ea254f9cb54d354a8ff17bd5b81",
2424
"authdigest": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2525
"depends": [],
2626
"fee": 0,

‎zebra-rpc/src/methods/tests/vectors.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,6 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
16011601
amount::NonNegative,
16021602
block::{Hash, MAX_BLOCK_BYTES, ZCASH_BLOCK_VERSION},
16031603
chain_sync_status::MockSyncStatus,
1604-
parameters::NetworkKind,
16051604
serialization::DateTime32,
16061605
transaction::{zip317, VerifiedUnminedTx},
16071606
work::difficulty::{CompactDifficulty, ExpandedDifficulty, U256},
@@ -1633,15 +1632,21 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
16331632
let mut mock_sync_status = MockSyncStatus::default();
16341633
mock_sync_status.set_is_close_to_tip(true);
16351634

1636-
let network = NetworkKind::Mainnet;
1635+
let network = Network::Mainnet;
16371636
let miner_address = match use_p2pkh {
1638-
false => Some(transparent::Address::from_script_hash(network, [0x7e; 20])),
1639-
true => Some(transparent::Address::from_pub_key_hash(network, [0x7e; 20])),
1637+
false => Some(transparent::Address::from_script_hash(
1638+
network.kind(),
1639+
[0x7e; 20],
1640+
)),
1641+
true => Some(transparent::Address::from_pub_key_hash(
1642+
network.kind(),
1643+
[0x7e; 20],
1644+
)),
16401645
};
16411646

16421647
#[allow(clippy::unnecessary_struct_initialization)]
16431648
let mining_config = crate::config::mining::Config {
1644-
miner_address,
1649+
miner_address: miner_address.clone(),
16451650
extra_coinbase_data: None,
16461651
debug_like_zcashd: true,
16471652
// TODO: Use default field values when optional features are enabled in tests #8183
@@ -1727,6 +1732,19 @@ async fn rpc_getblocktemplate_mining_address(use_p2pkh: bool) {
17271732
panic!("this getblocktemplate call without parameters should return the `TemplateMode` variant of the response")
17281733
};
17291734

1735+
let coinbase_transaction =
1736+
Transaction::zcash_deserialize(get_block_template.coinbase_txn.data.as_ref())
1737+
.expect("coinbase transaction data should be deserializable");
1738+
1739+
assert_eq!(
1740+
coinbase_transaction
1741+
.outputs()
1742+
.first()
1743+
.unwrap()
1744+
.address(&network),
1745+
miner_address
1746+
);
1747+
17301748
assert_eq!(
17311749
get_block_template.capabilities,
17321750
GET_BLOCK_TEMPLATE_CAPABILITIES_FIELD.to_vec()

0 commit comments

Comments
 (0)
Please sign in to comment.