From b077a7a02e0dc30b6f24370d57d34cf765859aa1 Mon Sep 17 00:00:00 2001 From: Mariano Sorgente Date: Fri, 3 Apr 2020 05:26:00 +0900 Subject: [PATCH] Fee parent val (#145) * Add validation of parent ids for coinbase and fees, and add 1 to height for fees * Increment protocol version * Add 1 to fee calculation * Fix test --- src/consensus/constants.py | 2 +- src/full_node/blockchain.py | 11 +++++++++++ src/full_node/full_node.py | 4 ++-- src/protocols/shared_protocol.py | 2 +- src/util/errors.py | 3 +++ src/wallet/wallet.py | 4 +++- tests/block_tools.py | 4 ++-- tests/wallet/test_wallet_sync.py | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/consensus/constants.py b/src/consensus/constants.py index 1d01949be80d..fca52a483031 100644 --- a/src/consensus/constants.py +++ b/src/consensus/constants.py @@ -27,7 +27,7 @@ constants: Dict[str, Any] = { "PROPAGATION_DELAY_THRESHOLD": 1500, # Hardcoded genesis block, generated using tests/block_tools.py # Replace this any time the constants change. - "GENESIS_BLOCK": b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x15N3\xd3\xf9H\xc2K\x96\xfe\xf2f\xa2\xbf\x87\x0e\x0f,\xd0\xd4\x0f6s\xb1".\\\xf5\x8a\xb4\x03\x84\x8e\xf9\xbb\xa1\xca\xdef3:\xe4?\x0c\xe5\xc6\x12\x80\x88\xbe_6 X\xf1\x83\xe8\x99\xdf)\xb8\xf6t\xe0;\x82\x17\xc5\xe5\x94\xb7\xef\xc2|\x94\xe6\xfb\x91L\x85\xe4\x00WVV\xefJ\x1e/>\xf6\xc5Gr5n\x13\x00\x00\x00\x98\xe4\xd8(mep\xcf}\xdb\xd7(\x04N"\xd1I\x18g\xae[\xff\xc0#z\xee\xb7\xbd3f\xe4zR3mi-\x89\x88\xbc\xd3\xf0|\xee\x03\x13\xc9}\xbb\x9b\x7f\x7f\xcfj\x08\x01\xe0*\x1e\x9an\xf6\xba\xd5\xb1\xc1\x80\x96\x8a\x99\xe3\x91\x92j\xce\xfdij\xea\xccT\xd0[\xd0\x89\xdc\xb8\xa3 /\xf27\x0f\x9ce\x87\x9dK\xe7\xab\x01\xbb\x1e\x91U\x95\x0f\xc0c\xa3\xa4\x81Um\x80_\xee\x8f3\xc7\xe3?\xf5\xacyF\x941\x90\x9e\xd1\xd0\x0bB\xa4\xa4\xe18\x13\xd5x\xca\xbd\x9b;\xf9B\xa1y\xaasm\x14\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x03\xaf\x99\x00I\x998~\xb9\x8e;\xed:\x19M\xcfp.\xd3A#8a\xb8\x9eee\xda\xfa\xff\xbc\x1ea\xcfN\xda\xde\x02\xe0\xc0\'3\xe41\x8b\xec\xda<@\xb4\x14,\xb5X)\xdbI\xdcS\xe8/\xfa$\n\xaf\xa6\xe0\xce\xff\xd0\x93x`\xb11\xc4\xa2I\xe1-\xd5\x1c\xc7\xef\x88\x05\xa8\x7f\xddp\x8ak\n\xa3\x96\x80L\xefV\xa2\x82\xfa\x92I\x14\x93\xb6\xfbW\n\xcf=W]\xcb\xc5\x0bf\xce4\x1d]\xb6"\t\x07\x82\x9f\xafq{D5\x00\x00\x00\x00\x82\x00\r\xe0\x13\x03bj\x9aPv\xbd{p\x10.#\xcf\xd3P4\x86?\xbawF\x9bS\x0cK\xd6\x0ex;\xd4\xd2\xc4\x90\xd0\x04"t\x1e\x8br\xd9\x8b@"\xb2\xdd\xb1\x11H\xd0s\'"\x1b\xaeeM\xb9\xe6\xe3\x1a\x00\t\x13\xb7\x94\xb6\xd5*\x90,)\x99n\t\x1b\xb4C4\x0fc~\xa7\xf3\x95\x04\xcc]\x17C\x94\x10\x8d\xde`\xc1\xa7\x93\xefb\xf3\xd9\xb9\x8f\x14\xc9\xdc\x18\xd8\xfd\xbd[\xf5\xb7\xaa\xd1\x8e\x01\x1c\x8eZ\x7f\xad\xdb\xc1M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^x\x84\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x93h\xb0E\x0c\xaa\xda1\x9a\x04\x83 \xedGe\xf1\'\xab\xc7Z\x9d\xaf!\x18D#\t\x0bz\xe2\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf4\x00\x00\x00\x00\x00\x03\xaf\x99\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8b)\xaa\x96x8\xd76J\xa6\x8b[\x98\t\xe0\\\xe3^7qD\x8c\xf5q\x08\xf2\xa2\xc9\xb03mv\x00\x00\x0c\xbb\xa1\x06\xe0\x00N\x1f\xe8;}6F\xd7\xec\xc7\x83\x16T\x96\x1f\xe6\x88,\xa4\x9b\xa3Lo\xd0\xe6\x89jW\xac\xba\xae)\xe9\x91?\x97\x0fU\xf5\xd8\xdc\x9e\xce\xbf~\xad\xc2\xbc\x17v|\x947N\x0e\xfa\xff\xe6;\xce@|\xe9{\xe2:\xa8H\xb4\xb9\xde;<;-\x9a\x03\xbf\xa3\xff\xed\x81\x0cd\x80|(I\x9e\x8c\xa5\x83\xdf\x8a\x1aX\xc1#\x19uE`)\xeblV\x1d\x8f\xe6\x1f\xfa\x03\xe2\xf4b\xdfO\x9c\x11\x1fHJ2\xbfvC\x8b^\x8b)\xaa\x96x8\xd76J\xa6\x8b[\x98\t\xe0\\\xe3^7qD\x8c\xf5q\x08\xf2\xa2\xc9\xb03mv\x00\x00\x01\xd1\xa9J \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$)\xcf\x82\xc23&\xedzR\x04\xb8Zz\xe9\x03\x94\xe1\x0f\xc2\xe1TS\xc2\xb6\xd1\xa5\xf2\xd6\xb4\xae\xfb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@q\xb3~\x8f\xa3\x14\xdd\x90\xe8\x9b.\xb8\x80\x9b^\x99\xd6_\xd5Qq5h\xbb\r\x87\x08\xb3\xb0)\n\x87\xf0\xa3\xc2\xc5\xc3\xf6=\x9f\x15\x83\xafW\xe1P\xcc\x14w~\x9b\xd4\xd3\ng\x18\x16\x14N%\xc0\x844\xc0\xad\xe5P\xe7r\\\xe9\xe2k \x1d\xeb+\xdd\x9f\x87\x1b\x8eb\xaf\xf1i\x03"\xcb\xce\x07\xff\x85\xdd\x97\x00\x00', # noqa: E501 + "GENESIS_BLOCK": b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x15N3\xd3\xf9H\xc2K\x96\xfe\xf2f\xa2\xbf\x87\x0e\x0f,\xd0\xd4\x0f6s\xb1".\\\xf5\x8a\xb4\x03\x84\x8e\xf9\xbb\xa1\xca\xdef3:\xe4?\x0c\xe5\xc6\x12\x80\x88\xbe_6 X\xf1\x83\xe8\x99\xdf)\xb8\xf6t\xe0;\x82\x17\xc5\xe5\x94\xb7\xef\xc2|\x94\xe6\xfb\x91L\x85\xe4\x00WVV\xefJ\x1e/>\xf6\xc5Gr5n\x13\x00\x00\x00\x98\xe4\xd8(mep\xcf}\xdb\xd7(\x04N"\xd1I\x18g\xae[\xff\xc0#z\xee\xb7\xbd3f\xe4zR3mi-\x89\x88\xbc\xd3\xf0|\xee\x03\x13\xc9}\xbb\x9b\x7f\x7f\xcfj\x08\x01\xe0*\x1e\x9an\xf6\xba\xd5\xb1\xc1\x80\x96\x8a\x99\xe3\x91\x92j\xce\xfdij\xea\xccT\xd0[\xd0\x89\xdc\xb8\xa3 /\xf27\x0f\x9ce\x87\x9dK\xe7\xab\x01\xbb\x1e\x91U\x95\x0f\xc0c\xa3\xa4\x81Um\x80_\xee\x8f3\xc7\xe3?\xf5\xacyF\x941\x90\x9e\xd1\xd0\x0bB\xa4\xa4\xe18\x13\xd5x\xca\xbd\x9b;\xf9B\xa1y\xaasm\x14\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x03\xaf\x99\x00I\x998~\xb9\x8e;\xed:\x19M\xcfp.\xd3A#8a\xb8\x9eee\xda\xfa\xff\xbc\x1ea\xcfN\xda\xde\x02\xe0\xc0\'3\xe41\x8b\xec\xda<@\xb4\x14,\xb5X)\xdbI\xdcS\xe8/\xfa$\n\xaf\xa6\xe0\xce\xff\xd0\x93x`\xb11\xc4\xa2I\xe1-\xd5\x1c\xc7\xef\x88\x05\xa8\x7f\xddp\x8ak\n\xa3\x96\x80L\xefV\xa2\x82\xfa\x92I\x14\x93\xb6\xfbW\n\xcf=W]\xcb\xc5\x0bf\xce4\x1d]\xb6"\t\x07\x82\x9f\xafq{D5\x00\x00\x00\x00\x82\x00\r\xe0\x13\x03bj\x9aPv\xbd{p\x10.#\xcf\xd3P4\x86?\xbawF\x9bS\x0cK\xd6\x0ex;\xd4\xd2\xc4\x90\xd0\x04"t\x1e\x8br\xd9\x8b@"\xb2\xdd\xb1\x11H\xd0s\'"\x1b\xaeeM\xb9\xe6\xe3\x1a\x00\t\x13\xb7\x94\xb6\xd5*\x90,)\x99n\t\x1b\xb4C4\x0fc~\xa7\xf3\x95\x04\xcc]\x17C\x94\x10\x8d\xde`\xc1\xa7\x93\xefb\xf3\xd9\xb9\x8f\x14\xc9\xdc\x18\xd8\xfd\xbd[\xf5\xb7\xaa\xd1\x8e\x01\x1c\x8eZ\x7f\xad\xdb\xc1M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x86Ch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x93h\xb0E\x0c\xaa\xda1\x9a\x04\x83 \xedGe\xf1\'\xab\xc7Z\x9d\xaf!\x18D#\t\x0bz\xe2\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf4\x00\x00\x00\x00\x00\x03\xaf\x99\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8b)\xaa\x96x8\xd76J\xa6\x8b[\x98\t\xe0\\\xe3^7qD\x8c\xf5q\x08\xf2\xa2\xc9\xb03mv\x00\x00\x0c\xbb\xa1\x06\xe0\x00N\x1f\xe8;}6F\xd7\xec\xc7\x83\x16T\x96\x1f\xe6\x88,\xa4\x9b\xa3Lo\xd0\xe6\x89jW\xac\xba\xae)\xe9\x91?\x97\x0fU\xf5\xd8\xdc\x9e\xce\xbf~\xad\xc2\xbc\x17v|\x947N\x0e\xfa\xff\xe6;\xce@|\xe9{\xe2:\xa8H\xb4\xb9\xde;<;-\x9a\x03\xbf\xa3\xff\xed\x81\x0cd\x80|(I\x9e\x8c\xa5\x83\xdf\x8a\x1aX\x8c\xb9\x01%\x17\xc8\x17\xfe\xade\x02\x87\xd6\x1b\xdd\x9ch\x80;k\xf9\xc6A3\xdc\xab>e\xb5\xa5\x0c\xb9\x8b)\xaa\x96x8\xd76J\xa6\x8b[\x98\t\xe0\\\xe3^7qD\x8c\xf5q\x08\xf2\xa2\xc9\xb03mv\x00\x00\x01\xd1\xa9J \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$)\xcf\x82\xc23&\xedzR\x04\xb8Zz\xe9\x03\x94\xe1\x0f\xc2\xe1TS\xc2\xb6\xd1\xa5\xf2\xd6\xb4\xae\xfb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00H\xb4H>o\xde\x85\x9b\xf7\xc8S\x80\xb1\xfb,\xe6Kb`\xc9\x95p\xf5\x11\xb6\xda7\x071\xe9Wf5\xa2x\xd15r/\x16\x16\x9c\xb9\x9c\xe6\x94\xbe3\x18\xc1n-{\xa9W\xaf\xc6\x17\xc6\xd7\xa5\xf3jCJ\xb1a\xc3U\xb2)\xbc\x04\xa7V\xa43E\x89\x83\xbfw*\x97MQ\x98\xc6!\xb1\xdey"\xa5@%\x00\x00', # noqa: E501 # Target tx count per sec "TX_PER_SEC": 20, # Size of mempool = 10x the size of block diff --git a/src/full_node/blockchain.py b/src/full_node/blockchain.py index 7261d8780683..687051099d7b 100644 --- a/src/full_node/blockchain.py +++ b/src/full_node/blockchain.py @@ -633,7 +633,18 @@ class Blockchain: if coinbase_reward != block.header.data.coinbase.amount: return (Err.INVALID_COINBASE_AMOUNT, None) + # 13b. The coinbase parent id must be the height + if block.header.data.coinbase.parent_coin_info != block.height.to_bytes( + 32, "big" + ): + return (Err.INVALID_COINBASE_PARENT, None) + + # 13c. The fees coin parent id must be hash(hash(height)) fee_base = calculate_base_fee(block.height) + if block.header.data.fees_coin.parent_coin_info != std_hash( + std_hash(uint32(block.height)) + ): + return (Err.INVALID_FEES_COIN_PARENT, None) # target reward_fee = 1/8 coinbase reward + tx fees if block.transactions_generator is not None: diff --git a/src/full_node/full_node.py b/src/full_node/full_node.py index 729e293298b2..3ce1f4e3666f 100644 --- a/src/full_node/full_node.py +++ b/src/full_node/full_node.py @@ -1293,10 +1293,10 @@ class FullNode: spend_bundle_fees = spend_bundle.fees() aggregate_sig = spend_bundle.aggregated_signature - base_fee_reward = calculate_base_fee(target_tip.height) + base_fee_reward = calculate_base_fee(target_tip.height + 1) full_fee_reward = uint64(int(base_fee_reward + spend_bundle_fees)) # Create fees coin - fee_hash = std_hash(std_hash(target_tip.height)) + fee_hash = std_hash(std_hash(uint32(target_tip.height + 1))) fees_coin = Coin(fee_hash, request.fees_target_puzzle_hash, full_fee_reward) # Calculate the cost of transactions diff --git a/src/protocols/shared_protocol.py b/src/protocols/shared_protocol.py index 363f9087623a..dd9b8e325bf9 100644 --- a/src/protocols/shared_protocol.py +++ b/src/protocols/shared_protocol.py @@ -5,7 +5,7 @@ from src.types.sized_bytes import bytes32 from src.util.cbor_message import cbor_message from src.util.ints import uint16 -protocol_version = "0.0.10" +protocol_version = "0.0.11" """ Handshake when establishing a connection between two servers. diff --git a/src/util/errors.py b/src/util/errors.py index 9238da96a4ee..0f21c244fccf 100644 --- a/src/util/errors.py +++ b/src/util/errors.py @@ -67,6 +67,9 @@ class Err(Enum): INVALID_POT_CHALLENGE = 43 INVALID_TRANSACTIONS_GENERATOR_HASH = 44 + INVALID_COINBASE_PARENT = 45 + INVALID_FEES_COIN_PARENT = 46 + class ConsensusError(Exception): def __init__(self, code: Err, errors: List[Any] = []): diff --git a/src/wallet/wallet.py b/src/wallet/wallet.py index aa1636e5fd56..8c2f51619bac 100644 --- a/src/wallet/wallet.py +++ b/src/wallet/wallet.py @@ -162,7 +162,9 @@ class Wallet: continue sum += coinrecord.coin.amount used_coins.add(coinrecord.coin) - self.log.info(f"Selected coin: {coinrecord.coin.name()}") + self.log.info( + f"Selected coin: {coinrecord.coin.name()} at height {coinrecord.confirmed_block_index}!" + ) # This happens when we couldn't use one of the coins because it's already used # but unconfirmed, and we are waiting for the change. (unconfirmed_additions) diff --git a/tests/block_tools.py b/tests/block_tools.py index 713346b92aef..6c3b6c8a9e16 100644 --- a/tests/block_tools.py +++ b/tests/block_tools.py @@ -445,8 +445,8 @@ class BlockTools: height, reward_puzzlehash, coinbase_reward, pool_sk ) - fee_hash = blspy.Util.hash256(coinbase_coin.name()) - fees_coin = Coin(fee_hash, reward_puzzlehash, uint64(fee_reward)) + parent_coin_name = std_hash(std_hash(height)) + fees_coin = Coin(parent_coin_name, reward_puzzlehash, uint64(fee_reward)) # Create filter byte_array_tx: List[bytes32] = [] diff --git a/tests/wallet/test_wallet_sync.py b/tests/wallet/test_wallet_sync.py index 9b62ea0e9928..1068bb28db27 100644 --- a/tests/wallet/test_wallet_sync.py +++ b/tests/wallet/test_wallet_sync.py @@ -391,7 +391,7 @@ class TestWalletSync: # Fee and coinbase assert len(records) == 2 assert records[0].spent != records[1].spent - assert records[0].coinbase != records[1].coinbase + assert records[0].coinbase == records[1].coinbase records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash( another_puzzlehash )