Skip to content

Commit d41b503

Browse files
committed
Merge bitcoin/bitcoin#33446: rpc: fix getblock(header) returns target for tip
bf7996c rpc: fix getblock(header) returns target for tip (Sjors Provoost) 4c3c1f4 test: add block 2016 to mock mainnet (Sjors Provoost) Pull request description: A `target` field was added to the `getblock` and `getblockheader` RPC calls in #31583, but it mistakingly always used the tip value. This PR fixes it to return the target for the given block. Because regtest does not have difficulty adjustment, the mainnet test is expanded to cover the fix. A preliminary commit deals with mining block 2016 that's needed for the test. It also: - renames the `create_coinbase` `retarget_period` argument to `halving_period`. Before #31583 this was hardcoded for regtest where these values are the same. - drops unused `fees` argument from `mine` helper - expands the CPU miner instructions for generating the alternative mainnet chain Fixes #33440 ACKs for top commit: sipa: utACK bf7996c luke-jr: crACK bf7996c TheCharlatan: ACK bf7996c ismaelsadeeq: Code review ACK bf7996c Tree-SHA512: 2a2e11efd91f4aaccf9d2ec4dff9fd82c366b8a7e797ce5981dca2e6f08028f69154f4e6a27aef20d78b0e6c3304416789267c2fad42d7aa5072f8537d0c8b0d
2 parents 5ae8edb + bf7996c commit d41b503

File tree

5 files changed

+43
-14
lines changed

5 files changed

+43
-14
lines changed

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
166166
result.pushKV("mediantime", blockindex.GetMedianTimePast());
167167
result.pushKV("nonce", blockindex.nNonce);
168168
result.pushKV("bits", strprintf("%08x", blockindex.nBits));
169-
result.pushKV("target", GetTarget(tip, pow_limit).GetHex());
169+
result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
170170
result.pushKV("difficulty", GetDifficulty(blockindex));
171171
result.pushKV("chainwork", blockindex.nChainWork.GetHex());
172172
result.pushKV("nTx", blockindex.nTx);

test/functional/data/README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ The alternate mainnet chain was generated as follows:
1111
- restart node with a faketime 2 minutes later
1212

1313
```sh
14-
for i in {1..2015}
14+
for i in {1..2016}
1515
do
16-
faketime "`date -d @"$(( 1231006505 + $i * 120 ))" +'%Y-%m-%d %H:%M:%S'`" \
16+
t=$(( 1231006505 + $i * 120 ))
17+
faketime "`date -d @$t +'%Y-%m-%d %H:%M:%S'`" \
1718
bitcoind -connect=0 -nocheckpoints -stopatheight=$i
1819
done
1920
```
2021

2122
The CPU miner is kept running as follows:
2223

2324
```sh
24-
./minerd --coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r --no-stratum --algo sha256d --no-longpoll --scantime 3 --retry-pause 1
25+
./minerd -u ... -p ... -o http://127.0.0.1:8332 --no-stratum \
26+
--coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r \
27+
--algo sha256d --no-longpoll --scantime 3 --retry-pause 1
2528
```
2629

2730
The payout address is derived from first BIP32 test vector master key:
@@ -40,3 +43,8 @@ The timestamp was not kept constant because at difficulty 1 it's not sufficient
4043
to only grind the nonce. Grinding the extra_nonce or version field instead
4144
would have required additional (stratum) software. It would also make it more
4245
complicated to reconstruct the blocks in this test.
46+
47+
The `getblocktemplate` RPC code needs to be patched to ignore not being connected
48+
to any peers, and to ignore the IBD status check.
49+
50+
On macOS use `faketime "@$t"` instead.

test/functional/data/mainnet_alt.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,7 +2014,8 @@
20142014
1231247971,
20152015
1231248071,
20162016
1231248198,
2017-
1231248322
2017+
1231248322,
2018+
1231248621
20182019
],
20192020
"nonces": [
20202021
2345621585,
@@ -4031,6 +4032,7 @@
40314032
3658502865,
40324033
2519048297,
40334034
1915965760,
4034-
1183846025
4035+
1183846025,
4036+
2713372123
40354037
]
40364038
}

test/functional/mining_mainnet.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ def add_options(self, parser):
5353
help='Block data file (default: %(default)s)',
5454
)
5555

56-
def mine(self, height, prev_hash, blocks, node, fees=0):
56+
def mine(self, height, prev_hash, blocks, node):
5757
self.log.debug(f"height={height}")
5858
block = CBlock()
5959
block.nVersion = 0x20000000
6060
block.hashPrevBlock = int(prev_hash, 16)
6161
block.nTime = blocks['timestamps'][height - 1]
62-
block.nBits = DIFF_1_N_BITS
62+
block.nBits = DIFF_1_N_BITS if height < 2016 else DIFF_4_N_BITS
6363
block.nNonce = blocks['nonces'][height - 1]
64-
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), retarget_period=2016)]
64+
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), halving_period=210000)]
6565
# The alternate mainnet chain was mined with non-timelocked coinbase txs.
6666
block.vtx[0].nLockTime = 0
6767
block.vtx[0].vin[0].nSequence = SEQUENCE_FINAL
@@ -82,12 +82,15 @@ def run_test(self):
8282
self.log.info("Load alternative mainnet blocks")
8383
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
8484
prev_hash = node.getbestblockhash()
85+
blocks = None
8586
with open(path, encoding='utf-8') as f:
8687
blocks = json.load(f)
8788
n_blocks = len(blocks['timestamps'])
88-
assert_equal(n_blocks, 2015)
89-
for i in range(2015):
90-
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
89+
assert_equal(n_blocks, 2016)
90+
91+
# Mine up to the last block of the first retarget period
92+
for i in range(2015):
93+
prev_hash = self.mine(i + 1, prev_hash, blocks, node)
9194

9295
assert_equal(node.getblockcount(), 2015)
9396

@@ -102,5 +105,21 @@ def run_test(self):
102105
assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS))
103106
assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET))
104107

108+
# Mine first block of the second retarget period
109+
height = 2016
110+
prev_hash = self.mine(height, prev_hash, blocks, node)
111+
assert_equal(node.getblockcount(), height)
112+
113+
mining_info = node.getmininginfo()
114+
assert_equal(mining_info['difficulty'], 4)
115+
116+
self.log.info("getblock RPC should show historical target")
117+
block_info = node.getblock(node.getblockhash(1))
118+
119+
assert_equal(block_info['difficulty'], 1)
120+
assert_equal(block_info['bits'], nbits_str(DIFF_1_N_BITS))
121+
assert_equal(block_info['target'], target_str(DIFF_1_TARGET))
122+
123+
105124
if __name__ == '__main__':
106125
MiningMainnetTest(__file__).main()

test/functional/test_framework/blocktools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def script_BIP34_coinbase_height(height):
144144
return CScript([CScriptNum(height)])
145145

146146

147-
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, retarget_period=REGTEST_RETARGET_PERIOD):
147+
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, halving_period=REGTEST_RETARGET_PERIOD):
148148
"""Create a coinbase transaction.
149149
150150
If pubkey is passed in, the coinbase output will be a P2PK output;
@@ -158,7 +158,7 @@ def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_scr
158158
coinbaseoutput = CTxOut()
159159
coinbaseoutput.nValue = nValue * COIN
160160
if nValue == 50:
161-
halvings = int(height / retarget_period)
161+
halvings = int(height / halving_period)
162162
coinbaseoutput.nValue >>= halvings
163163
coinbaseoutput.nValue += fees
164164
if pubkey is not None:

0 commit comments

Comments
 (0)