2020-01-30 04:28:53 +03:00
|
|
|
import asyncio
|
2020-02-01 03:28:16 +03:00
|
|
|
from time import time
|
2020-05-22 09:28:23 +03:00
|
|
|
from typing import List, Tuple
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-05-22 09:28:23 +03:00
|
|
|
import clvm
|
2020-01-30 04:28:53 +03:00
|
|
|
import pytest
|
2020-04-20 08:08:16 +03:00
|
|
|
from clvm.casts import int_to_bytes
|
2020-05-22 09:28:23 +03:00
|
|
|
from clvm_tools import binutils
|
2020-01-31 23:44:04 +03:00
|
|
|
|
2020-01-30 04:28:53 +03:00
|
|
|
from src.server.outbound_message import OutboundMessage
|
2020-02-09 00:21:03 +03:00
|
|
|
from src.protocols import full_node_protocol
|
2020-05-22 09:28:23 +03:00
|
|
|
from src.types.BLSSignature import BLSSignature
|
|
|
|
from src.types.coin_solution import CoinSolution
|
2020-02-27 05:23:03 +03:00
|
|
|
from src.types.condition_var_pair import ConditionVarPair
|
2020-02-03 08:59:00 +03:00
|
|
|
from src.types.condition_opcodes import ConditionOpcode
|
2020-05-22 09:28:23 +03:00
|
|
|
from src.types.program import Program
|
2020-03-30 20:27:22 +03:00
|
|
|
from src.types.spend_bundle import SpendBundle
|
2020-05-26 09:36:04 +03:00
|
|
|
from src.util.condition_tools import (
|
|
|
|
conditions_for_solution,
|
|
|
|
conditions_by_opcode,
|
|
|
|
hash_key_pairs_for_conditions_dict,
|
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
from src.util.ints import uint64
|
2020-01-30 04:28:53 +03:00
|
|
|
from tests.setup_nodes import setup_two_nodes, test_constants, bt
|
2020-01-31 03:56:24 +03:00
|
|
|
from tests.wallet_tools import WalletTool
|
2020-01-30 04:28:53 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def event_loop():
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
yield loop
|
|
|
|
|
|
|
|
|
|
|
|
class TestMempool:
|
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
async def two_nodes(self):
|
2020-02-02 10:52:33 +03:00
|
|
|
async for _ in setup_two_nodes({"COINBASE_FREEZE_PERIOD": 0}):
|
|
|
|
yield _
|
|
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
async def two_nodes_standard_freeze(self):
|
|
|
|
async for _ in setup_two_nodes({"COINBASE_FREEZE_PERIOD": 200}):
|
2020-01-30 04:28:53 +03:00
|
|
|
yield _
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_basic_mempool(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-01-31 03:56:24 +03:00
|
|
|
wallet_a = WalletTool()
|
2020-01-30 04:28:53 +03:00
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
2020-02-01 03:28:16 +03:00
|
|
|
wallet_receiver = WalletTool()
|
2020-01-30 04:28:53 +03:00
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-01-30 04:28:53 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
2020-02-02 10:52:33 +03:00
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-02-02 10:52:33 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-03-30 12:03:03 +03:00
|
|
|
assert spend_bundle is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx):
|
2020-02-02 10:52:33 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-02-02 10:52:33 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
2020-02-02 10:52:33 +03:00
|
|
|
assert sb is spend_bundle
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_coinbase_freeze(self, two_nodes_standard_freeze):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-02 10:52:33 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-02 10:52:33 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes_standard_freeze
|
|
|
|
|
2020-01-30 04:28:53 +03:00
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-02-02 10:52:33 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
|
|
|
assert spend_bundle is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle
|
|
|
|
)
|
2020-02-02 10:52:33 +03:00
|
|
|
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx):
|
2020-02-02 10:52:33 +03:00
|
|
|
outbound: OutboundMessage = _
|
2020-02-05 15:07:18 +03:00
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function != "new_transaction"
|
2020-02-02 10:52:33 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
2020-02-02 10:52:33 +03:00
|
|
|
assert sb is None
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, 200, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-02 10:52:33 +03:00
|
|
|
|
|
|
|
for i in range(1, 201):
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(blocks[i])
|
|
|
|
):
|
2020-02-02 10:52:33 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx):
|
2020-02-05 15:07:18 +03:00
|
|
|
outbound_2: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound_2.message.function == "new_transaction"
|
2020-02-14 23:48:41 +03:00
|
|
|
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
2020-02-02 10:52:33 +03:00
|
|
|
assert sb is spend_bundle
|
2020-01-30 04:28:53 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_double_spend(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-01-31 03:56:24 +03:00
|
|
|
wallet_a = WalletTool()
|
2020-01-30 04:28:53 +03:00
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
2020-01-31 03:56:24 +03:00
|
|
|
wallet_receiver = WalletTool()
|
2020-01-30 04:28:53 +03:00
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-01-30 04:28:53 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-01-30 04:28:53 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-01-30 04:28:53 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-01-30 04:28:53 +03:00
|
|
|
|
2020-01-31 03:56:24 +03:00
|
|
|
other_receiver = WalletTool()
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle2 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, other_receiver.get_new_puzzlehash(), block.header.data.coinbase
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
|
|
|
assert spend_bundle2 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle2
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx2):
|
2020-01-30 04:28:53 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
|
|
|
sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
2020-01-30 04:28:53 +03:00
|
|
|
|
|
|
|
assert sb1 == spend_bundle1
|
|
|
|
assert sb2 is None
|
|
|
|
|
2020-01-31 03:56:24 +03:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_double_spend_with_higher_fee(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-01-31 03:56:24 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-01-31 03:56:24 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-01-31 03:56:24 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-01-31 03:56:24 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-01-31 03:56:24 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle2 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, fee=1
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-01-31 03:56:24 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle2 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle2
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx2):
|
2020-01-31 03:56:24 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
|
|
|
sb2 = full_node_1.mempool_manager.get_spendbundle(spend_bundle2.name())
|
2020-01-31 03:56:24 +03:00
|
|
|
|
|
|
|
assert sb1 is None
|
|
|
|
assert sb2 == spend_bundle2
|
|
|
|
|
2020-01-31 23:44:04 +03:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_invalid_block_index(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-01-31 23:44:04 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-01-31 23:44:04 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS,
|
|
|
|
uint64(2).to_bytes(4, "big"),
|
|
|
|
None,
|
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-01-31 23:44:04 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function != "new_transaction"
|
2020-01-31 23:44:04 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-01-31 23:44:04 +03:00
|
|
|
|
|
|
|
assert sb1 is None
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_correct_block_index(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-01-31 23:44:04 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-01-31 23:44:04 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS,
|
|
|
|
uint64(1).to_bytes(4, "big"),
|
|
|
|
None,
|
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-01-31 23:44:04 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-01-31 23:44:04 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-01-31 23:44:04 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-01-31 23:44:04 +03:00
|
|
|
|
|
|
|
assert sb1 is spend_bundle1
|
|
|
|
|
2020-02-01 01:19:35 +03:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_invalid_block_age(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-01 01:19:35 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
2020-02-01 01:19:35 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, uint64(5).to_bytes(4, "big"), None
|
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 01:19:35 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function != "new_transaction"
|
2020-02-01 01:19:35 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 01:19:35 +03:00
|
|
|
|
|
|
|
assert sb1 is None
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_correct_block_age(self, two_nodes):
|
|
|
|
num_blocks = 4
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
2020-02-01 01:19:35 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, uint64(3).to_bytes(4, "big"), None
|
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:19:35 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 01:19:35 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-02-01 01:19:35 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 01:19:35 +03:00
|
|
|
|
|
|
|
assert sb1 is spend_bundle1
|
|
|
|
|
2020-02-01 01:58:07 +03:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_correct_my_id(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-01 01:58:07 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
2020-02-01 01:58:07 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
2020-03-02 09:06:03 +03:00
|
|
|
ConditionOpcode.ASSERT_MY_COIN_ID, block.header.data.coinbase.name(), None
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 01:58:07 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-02-01 01:58:07 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 01:58:07 +03:00
|
|
|
|
|
|
|
assert sb1 is spend_bundle1
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_invalid_my_id(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-01 01:58:07 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
2020-02-01 01:58:07 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
2020-03-02 09:06:03 +03:00
|
|
|
ConditionOpcode.ASSERT_MY_COIN_ID,
|
|
|
|
blocks[2].header.data.coinbase.name(),
|
|
|
|
None,
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 01:58:07 +03:00
|
|
|
|
2020-03-30 12:03:03 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 01:58:07 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function != "new_transaction"
|
2020-02-01 01:58:07 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 01:58:07 +03:00
|
|
|
|
|
|
|
assert sb1 is None
|
2020-02-01 03:28:16 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_assert_time_exceeds(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-01 03:28:16 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
2020-02-01 03:28:16 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
time_now = uint64(int(time() * 1000))
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now.to_bytes(8, "big"), None
|
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-03-30 12:03:03 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 03:28:16 +03:00
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function == "new_transaction"
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 03:28:16 +03:00
|
|
|
|
|
|
|
assert sb1 is spend_bundle1
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_assert_time_exceeds_both_cases(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-01 03:28:16 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
2020-02-01 03:28:16 +03:00
|
|
|
pass
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
time_now = uint64(int(time() * 1000))
|
2020-02-01 03:29:15 +03:00
|
|
|
time_now_plus_3 = time_now + 3000
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
cvp = ConditionVarPair(
|
|
|
|
ConditionOpcode.ASSERT_TIME_EXCEEDS,
|
|
|
|
time_now_plus_3.to_bytes(8, "big"),
|
|
|
|
None,
|
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:06:03 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-05 15:07:18 +03:00
|
|
|
)
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-14 21:03:56 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
2020-02-01 03:28:16 +03:00
|
|
|
outbound: OutboundMessage = _
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound.message.function != "new_transaction"
|
2020-02-01 03:28:16 +03:00
|
|
|
|
|
|
|
# Sleep so that 3 sec passes
|
|
|
|
await asyncio.sleep(3)
|
|
|
|
|
2020-02-14 21:03:56 +03:00
|
|
|
tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
2020-02-10 20:08:58 +03:00
|
|
|
spend_bundle1
|
|
|
|
)
|
2020-02-14 21:03:56 +03:00
|
|
|
async for _ in full_node_1.respond_transaction(tx2):
|
2020-02-05 15:07:18 +03:00
|
|
|
outbound_2: OutboundMessage = _
|
2020-02-01 03:28:16 +03:00
|
|
|
# Maybe transaction means that it's accepted in mempool
|
2020-02-14 21:03:56 +03:00
|
|
|
assert outbound_2.message.function == "new_transaction"
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-14 23:48:41 +03:00
|
|
|
sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name())
|
2020-02-01 03:28:16 +03:00
|
|
|
|
2020-02-05 15:07:18 +03:00
|
|
|
assert sb1 is spend_bundle1
|
2020-02-28 00:44:24 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_correct_coin_consumed(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-28 00:44:24 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
block2 = blocks[2]
|
|
|
|
|
|
|
|
for b in blocks:
|
|
|
|
async for _ in full_node_1.respond_block(
|
2020-02-29 04:54:44 +03:00
|
|
|
full_node_protocol.RespondBlock(b)
|
2020-02-28 00:44:24 +03:00
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
|
|
|
cvp = ConditionVarPair(
|
2020-03-02 09:17:20 +03:00
|
|
|
ConditionOpcode.ASSERT_COIN_CONSUMED,
|
|
|
|
block2.header.data.coinbase.name(),
|
|
|
|
None,
|
2020-02-28 00:44:24 +03:00
|
|
|
)
|
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:17:20 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-28 00:44:24 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
spend_bundle2 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:17:20 +03:00
|
|
|
1000, receiver_puzzlehash, block2.header.data.coinbase
|
2020-02-28 00:44:24 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2])
|
|
|
|
|
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
bundle
|
|
|
|
)
|
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
|
|
|
assert outbound.message.function == "new_transaction"
|
|
|
|
|
|
|
|
mempool_bundle = full_node_1.mempool_manager.get_spendbundle(bundle.name())
|
|
|
|
|
|
|
|
assert mempool_bundle is bundle
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_invalid_coin_consumed(self, two_nodes):
|
2020-02-28 01:29:01 +03:00
|
|
|
num_blocks = 2
|
2020-02-28 00:44:24 +03:00
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
block2 = blocks[2]
|
|
|
|
|
|
|
|
for b in blocks:
|
|
|
|
async for _ in full_node_1.respond_block(
|
2020-02-29 04:54:44 +03:00
|
|
|
full_node_protocol.RespondBlock(b)
|
2020-02-28 00:44:24 +03:00
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
|
|
|
cvp = ConditionVarPair(
|
2020-03-02 09:17:20 +03:00
|
|
|
ConditionOpcode.ASSERT_COIN_CONSUMED,
|
|
|
|
block2.header.data.coinbase.name(),
|
|
|
|
None,
|
2020-02-28 00:44:24 +03:00
|
|
|
)
|
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
2020-03-02 09:17:20 +03:00
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic
|
2020-02-28 00:44:24 +03:00
|
|
|
)
|
|
|
|
|
2020-03-30 12:03:03 +03:00
|
|
|
assert spend_bundle1 is not None
|
2020-02-28 00:44:24 +03:00
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle1
|
|
|
|
)
|
|
|
|
async for _ in full_node_1.respond_transaction(tx1):
|
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
|
|
|
assert outbound.message.function == "new_transaction"
|
|
|
|
|
2020-02-29 04:54:44 +03:00
|
|
|
mempool_bundle = full_node_1.mempool_manager.get_spendbundle(
|
|
|
|
spend_bundle1.name()
|
|
|
|
)
|
2020-02-28 00:44:24 +03:00
|
|
|
|
|
|
|
assert mempool_bundle is None
|
2020-04-20 08:08:16 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_assert_fee_condition(self, two_nodes):
|
|
|
|
num_blocks = 2
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
2020-04-20 08:10:19 +03:00
|
|
|
cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None,)
|
2020-04-20 08:08:16 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic, 10
|
|
|
|
)
|
|
|
|
|
|
|
|
assert spend_bundle1 is not None
|
|
|
|
|
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle1
|
|
|
|
)
|
|
|
|
|
|
|
|
outbound_messages: List[OutboundMessage] = []
|
|
|
|
async for outbound in full_node_1.respond_transaction(tx1):
|
|
|
|
outbound_messages.append(outbound)
|
|
|
|
|
|
|
|
new_transaction = False
|
|
|
|
for msg in outbound_messages:
|
|
|
|
if msg.message.function == "new_transaction":
|
|
|
|
new_transaction = True
|
|
|
|
|
|
|
|
assert new_transaction == True
|
|
|
|
|
|
|
|
mempool_bundle = full_node_1.mempool_manager.get_spendbundle(
|
|
|
|
spend_bundle1.name()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert mempool_bundle is not None
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_assert_fee_condition_wrong_fee(self, two_nodes):
|
|
|
|
num_blocks = 2
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
|
|
|
|
for b in blocks:
|
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(b)
|
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
2020-04-20 08:10:19 +03:00
|
|
|
cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None,)
|
2020-04-20 08:08:16 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic, 9
|
|
|
|
)
|
|
|
|
|
|
|
|
assert spend_bundle1 is not None
|
|
|
|
|
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle1
|
|
|
|
)
|
|
|
|
|
|
|
|
outbound_messages: List[OutboundMessage] = []
|
|
|
|
async for outbound in full_node_1.respond_transaction(tx1):
|
|
|
|
outbound_messages.append(outbound)
|
|
|
|
|
|
|
|
new_transaction = False
|
|
|
|
for msg in outbound_messages:
|
|
|
|
if msg.message.function == "new_transaction":
|
|
|
|
new_transaction = True
|
|
|
|
|
|
|
|
assert new_transaction == False
|
|
|
|
|
|
|
|
mempool_bundle = full_node_1.mempool_manager.get_spendbundle(
|
|
|
|
spend_bundle1.name()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert mempool_bundle is None
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_stealing_fee(self, two_nodes):
|
|
|
|
num_blocks = 2
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, blocks, 10, b"", receiver_puzzlehash
|
|
|
|
)
|
|
|
|
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
wallet_2_block = blocks[3]
|
|
|
|
|
|
|
|
for b in blocks:
|
|
|
|
async for _ in full_node_1.respond_block(
|
2020-04-20 08:10:19 +03:00
|
|
|
full_node_protocol.RespondBlock(b)
|
2020-04-20 08:08:16 +03:00
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
2020-04-20 08:10:19 +03:00
|
|
|
cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None,)
|
2020-04-20 08:08:16 +03:00
|
|
|
dic = {cvp.opcode: [cvp]}
|
|
|
|
|
|
|
|
fee = 9
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, dic, fee
|
|
|
|
)
|
|
|
|
|
|
|
|
wallet_2_coinbase = wallet_2_block.header.data.coinbase
|
2020-04-20 08:10:19 +03:00
|
|
|
steal_fee_spendbundle = wallet_receiver.generate_signed_transaction(
|
|
|
|
wallet_2_coinbase.amount + fee, receiver_puzzlehash, wallet_2_coinbase
|
|
|
|
)
|
2020-04-20 08:08:16 +03:00
|
|
|
|
|
|
|
assert spend_bundle1 is not None
|
|
|
|
assert steal_fee_spendbundle is not None
|
|
|
|
|
|
|
|
combined = SpendBundle.aggregate([spend_bundle1, steal_fee_spendbundle])
|
|
|
|
|
|
|
|
assert combined.fees() == 0
|
|
|
|
|
|
|
|
tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle1
|
|
|
|
)
|
|
|
|
|
|
|
|
outbound_messages: List[OutboundMessage] = []
|
|
|
|
async for outbound in full_node_1.respond_transaction(tx1):
|
|
|
|
outbound_messages.append(outbound)
|
|
|
|
|
|
|
|
new_transaction = False
|
|
|
|
for msg in outbound_messages:
|
|
|
|
if msg.message.function == "new_transaction":
|
|
|
|
new_transaction = True
|
|
|
|
|
|
|
|
assert new_transaction == False
|
|
|
|
|
|
|
|
mempool_bundle = full_node_1.mempool_manager.get_spendbundle(
|
|
|
|
spend_bundle1.name()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert mempool_bundle is None
|
2020-04-29 23:41:42 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
2020-04-29 23:45:05 +03:00
|
|
|
async def test_double_spend_same_bundle(self, two_nodes):
|
2020-04-29 23:41:42 +03:00
|
|
|
num_blocks = 2
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
|
|
|
spend_bundle1 = wallet_a.generate_signed_transaction(
|
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase
|
|
|
|
)
|
|
|
|
|
|
|
|
assert spend_bundle1 is not None
|
|
|
|
|
|
|
|
other_receiver = WalletTool()
|
|
|
|
spend_bundle2 = wallet_a.generate_signed_transaction(
|
|
|
|
1000, other_receiver.get_new_puzzlehash(), block.header.data.coinbase
|
|
|
|
)
|
|
|
|
|
|
|
|
assert spend_bundle2 is not None
|
|
|
|
|
|
|
|
spend_bundle_combined = SpendBundle.aggregate([spend_bundle1, spend_bundle2])
|
|
|
|
|
|
|
|
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle_combined
|
|
|
|
)
|
|
|
|
messages = []
|
|
|
|
async for outbound in full_node_1.respond_transaction(tx):
|
|
|
|
messages.append(outbound)
|
|
|
|
|
|
|
|
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle_combined.name())
|
|
|
|
assert sb is None
|
2020-05-22 09:28:23 +03:00
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
async def test_agg_sig_condition(self, two_nodes):
|
|
|
|
num_blocks = 2
|
|
|
|
wallet_a = WalletTool()
|
|
|
|
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
|
|
|
|
wallet_receiver = WalletTool()
|
|
|
|
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
|
|
|
|
|
|
|
|
blocks = bt.get_consecutive_blocks(
|
|
|
|
test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
|
|
|
|
)
|
|
|
|
full_node_1, full_node_2, server_1, server_2 = two_nodes
|
|
|
|
|
|
|
|
block = blocks[1]
|
|
|
|
async for _ in full_node_1.respond_block(
|
|
|
|
full_node_protocol.RespondBlock(block)
|
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
2020-05-26 09:36:04 +03:00
|
|
|
unsigned: List[
|
|
|
|
Tuple[Program, CoinSolution]
|
|
|
|
] = wallet_a.generate_unsigned_transaction(
|
|
|
|
1000, receiver_puzzlehash, block.header.data.coinbase, {}, 0
|
|
|
|
)
|
2020-05-22 09:28:23 +03:00
|
|
|
assert len(unsigned) == 1
|
|
|
|
|
|
|
|
puzzle, solution = unsigned[0]
|
|
|
|
code_ = [puzzle, solution.solution]
|
|
|
|
sexp = Program.to(code_)
|
|
|
|
|
|
|
|
err, con, cost = conditions_for_solution(sexp)
|
|
|
|
assert con is not None
|
|
|
|
|
|
|
|
conditions_dict = conditions_by_opcode(con)
|
2020-05-26 09:36:04 +03:00
|
|
|
hash_key_pairs = hash_key_pairs_for_conditions_dict(
|
|
|
|
conditions_dict, solution.coin.name()
|
|
|
|
)
|
2020-05-22 09:28:23 +03:00
|
|
|
assert len(hash_key_pairs) == 1
|
|
|
|
|
|
|
|
pk_pair: BLSSignature.PkMessagePair = hash_key_pairs[0]
|
|
|
|
assert pk_pair.message_hash == solution.solution.first().get_tree_hash()
|
|
|
|
|
|
|
|
spend_bundle = wallet_a.sign_transaction(unsigned)
|
|
|
|
assert spend_bundle is not None
|
|
|
|
|
|
|
|
tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
|
|
|
|
spend_bundle
|
|
|
|
)
|
|
|
|
async for _ in full_node_1.respond_transaction(tx):
|
|
|
|
outbound: OutboundMessage = _
|
|
|
|
# Maybe transaction means that it's accepted in mempool
|
|
|
|
assert outbound.message.function == "new_transaction"
|
|
|
|
|
|
|
|
sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
|
|
|
|
assert sb is spend_bundle
|