Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864534
D1138.id3048.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Subscribers
None
D1138.id3048.diff
View Options
diff --git a/test/functional/abc-p2p-fullblocktest.py b/test/functional/abc-p2p-fullblocktest.py
--- a/test/functional/abc-p2p-fullblocktest.py
+++ b/test/functional/abc-p2p-fullblocktest.py
@@ -20,6 +20,7 @@
from test_framework.script import *
from test_framework.cdefs import (ONE_MEGABYTE, LEGACY_MAX_BLOCK_SIZE,
MAX_BLOCK_SIGOPS_PER_MB, MAX_TX_SIGOPS_COUNT)
+from collections import deque
class PreviousSpendableOutput():
@@ -70,12 +71,9 @@
self.num_nodes = 1
self.setup_clean_chain = True
self.block_heights = {}
- self.coinbase_key = CECKey()
- self.coinbase_key.set_secretbytes(b"fatstacks")
- self.coinbase_pubkey = self.coinbase_key.get_pubkey()
self.tip = None
self.blocks = {}
- self.excessive_block_size = 64 * ONE_MEGABYTE
+ self.excessive_block_size = 100 * ONE_MEGABYTE
self.extra_args = [['-norelaypriority',
'-whitelist=127.0.0.1',
'-limitancestorcount=9999',
@@ -109,31 +107,7 @@
tx = create_transaction(spend_tx, n, b"", value, script)
return tx
- # sign a transaction, using the key we know about
- # this signs input 0 in tx, which is assumed to be spending output n in
- # spend_tx
- def sign_tx(self, tx, spend_tx, n):
- scriptPubKey = bytearray(spend_tx.vout[n].scriptPubKey)
- if (scriptPubKey[0] == OP_TRUE): # an anyone-can-spend
- tx.vin[0].scriptSig = CScript()
- return
- sighash = SignatureHashForkId(
- spend_tx.vout[n].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, spend_tx.vout[n].nValue)
- tx.vin[0].scriptSig = CScript(
- [self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))])
-
- def create_and_sign_transaction(self, spend_tx, n, value, script=CScript([OP_TRUE])):
- tx = self.create_tx(spend_tx, n, value, script)
- self.sign_tx(tx, spend_tx, n)
- tx.rehash()
- return tx
-
- def next_block(self, number, spend=None, additional_coinbase_value=0, script=None, extra_sigops=0, block_size=0, solve=True):
- """
- Create a block on top of self.tip, and advance self.tip to point to the new block
- if spend is specified, then 1 satoshi will be spent from that to an anyone-can-spend
- output, and rest will go to fees.
- """
+ def next_block(self, number, spend=None, script=CScript([OP_TRUE]), block_size=0, extra_sigops=0):
if self.tip == None:
base_block_hash = self.genesis_hash
block_time = int(time.time()) + 1
@@ -142,70 +116,90 @@
block_time = self.tip.nTime + 1
# First create the coinbase
height = self.block_heights[base_block_hash] + 1
- coinbase = create_coinbase(height, self.coinbase_pubkey)
- coinbase.vout[0].nValue += additional_coinbase_value
- if (spend != None):
- coinbase.vout[0].nValue += spend.tx.vout[
- spend.n].nValue - 1 # all but one satoshi to fees
+ coinbase = create_coinbase(height)
coinbase.rehash()
- block = create_block(base_block_hash, coinbase, block_time)
- spendable_output = None
- if (spend != None):
+ if spend == None:
+ # We need to have something to spend to fill the block.
+ assert_equal(block_size, 0)
+ block = create_block(base_block_hash, coinbase, block_time)
+ else:
+ # all but one satoshi to fees
+ coinbase.vout[0].nValue += spend.tx.vout[spend.n].nValue - 1
+ coinbase.rehash()
+ block = create_block(base_block_hash, coinbase, block_time)
+ # spend 1 satoshi
tx = CTransaction()
- # no signature yet
- tx.vin.append(
- CTxIn(COutPoint(spend.tx.sha256, spend.n), b"", 0xffffffff))
- # We put some random data into the first transaction of the chain
- # to randomize ids
- tx.vout.append(
- CTxOut(0, CScript([random.randint(0, 255), OP_DROP, OP_TRUE])))
- if script == None:
- tx.vout.append(CTxOut(1, CScript([OP_TRUE])))
- else:
+ tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n)))
+ # Make sure we have plenty engough to spend going forward.
+ spendable_outputs = deque([])
+
+ def add_spendable_outputs(tx):
+ for i in range(8):
+ tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ spendable_outputs.append(PreviousSpendableOutput(tx, i))
+ add_spendable_outputs(tx)
+
+ # Make it the same format as transaction added for padding and save the size.
+ # It's missing the padding output, so we add a constant to account for it.
+ tx.rehash()
+ base_tx_size = len(tx.serialize()) + 18
+
+ # If a specific script is required, add it.
+ if script != None:
tx.vout.append(CTxOut(1, script))
- spendable_output = PreviousSpendableOutput(tx, 0)
- # Now sign it if necessary
- scriptSig = b""
- scriptPubKey = bytearray(spend.tx.vout[spend.n].scriptPubKey)
- if (scriptPubKey[0] == OP_TRUE): # looks like an anyone-can-spend
- scriptSig = CScript([OP_TRUE])
- else:
- # We have to actually sign it
- sighash = SignatureHashForkId(
- spend.tx.vout[spend.n].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, spend.tx.vout[spend.n].nValue)
- scriptSig = CScript(
- [self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))])
- tx.vin[0].scriptSig = scriptSig
- # Now add the transaction to the block
+ # Put some random data into the first transaction of the chain to randomize ids.
+ tx.vout.append(
+ CTxOut(0, CScript([random.randint(0, 256), OP_RETURN])))
+
+ # Add the transaction to the block
self.add_transactions_to_block(block, [tx])
- block.hashMerkleRoot = block.calc_merkle_root()
- if spendable_output != None and block_size > 0:
- while len(block.serialize()) < block_size:
+
+ # If we have a block size requirement, just fill
+ # the block until we get there
+ current_block_size = len(block.serialize())
+ while current_block_size < block_size:
+ # We will add a new transaction. That means the size of
+ # the field enumerating how many transaction go in the block
+ # may change.
+ current_block_size -= len(ser_compact_size(len(block.vtx)))
+ current_block_size += len(ser_compact_size(len(block.vtx) + 1))
+
+ # Create the new transaction
tx = CTransaction()
- script_length = block_size - len(block.serialize()) - 79
+ # Spend from one of the spendable outputs
+ spend = spendable_outputs.popleft()
+ tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n)))
+ # Add spendable outputs
+ add_spendable_outputs(tx)
+
+ # Add padding to fill the block.
+ script_length = block_size - current_block_size - base_tx_size
if script_length > 510000:
script_length = 500000
- tx_sigops = min(
- extra_sigops, script_length, MAX_TX_SIGOPS_COUNT)
+ tx_sigops = min(extra_sigops, script_length,
+ MAX_TX_SIGOPS_COUNT)
extra_sigops -= tx_sigops
script_pad_len = script_length - tx_sigops
script_output = CScript(
[b'\x00' * script_pad_len] + [OP_CHECKSIG] * tx_sigops)
- tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
tx.vout.append(CTxOut(0, script_output))
- tx.vin.append(
- CTxIn(COutPoint(spendable_output.tx.sha256, spendable_output.n)))
- spendable_output = PreviousSpendableOutput(tx, 0)
+
+ # Add the tx to the list of transactions to be included
+ # in the block.
self.add_transactions_to_block(block, [tx])
+ current_block_size += len(tx.serialize())
+
+ # Now that we added a bunch of transaction, we need to recompute
+ # the merkle root.
block.hashMerkleRoot = block.calc_merkle_root()
- # Make sure the math above worked out to produce the correct block size
- # (the math will fail if there are too many transactions in the block)
+
+ # Check that the block size is what's expected
+ if block_size > 0:
assert_equal(len(block.serialize()), block_size)
- # Make sure all the requested sigops have been included
- assert_equal(extra_sigops, 0)
- if solve:
- block.solve()
+
+ # Do PoW, which is cheap on regnet
+ block.solve()
self.tip = block
self.block_heights[block.sha256] = height
assert number not in self.blocks
@@ -296,15 +290,13 @@
# Accept many sigops
lots_of_checksigs = CScript(
- [OP_CHECKSIG] * (MAX_BLOCK_SIGOPS_PER_MB - 1))
- block(
- 19, spend=out[17], script=lots_of_checksigs, block_size=ONE_MEGABYTE)
+ [OP_CHECKSIG] * MAX_BLOCK_SIGOPS_PER_MB)
+ block(19, spend=out[17], script=lots_of_checksigs,
+ block_size=ONE_MEGABYTE)
yield accepted()
- too_many_blk_checksigs = CScript(
- [OP_CHECKSIG] * MAX_BLOCK_SIGOPS_PER_MB)
- block(
- 20, spend=out[18], script=too_many_blk_checksigs, block_size=ONE_MEGABYTE)
+ block(20, spend=out[18], script=lots_of_checksigs,
+ block_size=ONE_MEGABYTE, extra_sigops=1)
yield rejected(RejectResult(16, b'bad-blk-sigops'))
# Rewind bad block
@@ -372,16 +364,20 @@
# Rewind bad block
tip(26)
+ # Generate a key pair to test P2SH sigops count
+ private_key = CECKey()
+ private_key.set_secretbytes(b"fatstacks")
+ public_key = private_key.get_pubkey()
+
# P2SH
# Build the redeem script, hash it, use hash to create the p2sh script
- redeem_script = CScript([self.coinbase_pubkey] + [
- OP_2DUP, OP_CHECKSIGVERIFY] * 5 + [OP_CHECKSIG])
+ redeem_script = CScript(
+ [public_key] + [OP_2DUP, OP_CHECKSIGVERIFY] * 5 + [OP_CHECKSIG])
redeem_script_hash = hash160(redeem_script)
p2sh_script = CScript([OP_HASH160, redeem_script_hash, OP_EQUAL])
# Create a p2sh transaction
- p2sh_tx = self.create_and_sign_transaction(
- out[22].tx, out[22].n, 1, p2sh_script)
+ p2sh_tx = self.create_tx(out[22].tx, out[22].n, 1, p2sh_script)
# Add the transaction to the block
block(30)
@@ -398,8 +394,8 @@
# Sign the transaction using the redeem script
sighash = SignatureHashForkId(
redeem_script, spent_p2sh_tx, 0, SIGHASH_ALL | SIGHASH_FORKID, p2sh_tx.vout[0].nValue)
- sig = self.coinbase_key.sign(sighash) + bytes(
- bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
+ sig = private_key.sign(sighash) + \
+ bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
spent_p2sh_tx.vin[0].scriptSig = CScript([sig, redeem_script])
spent_p2sh_tx.rehash()
return spent_p2sh_tx
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 20, 20:21 (7 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865868
Default Alt Text
D1138.id3048.diff (11 KB)
Attached To
D1138: Optimize abc-p2p-fullblocktest
Event Timeline
Log In to Comment