Skip to content

Commit

Permalink
Start full node tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mariano54 committed Feb 17, 2020
1 parent 96545b6 commit 3250f1f
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 36 deletions.
2 changes: 1 addition & 1 deletion src/mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def add_to_pool(
if self.at_full_capacity():
# Val is Dict[hash, MempoolItem]
fee_per_cost, val = self.sorted_spends.peekitem(index=0)
to_remove = val.values()[0]
to_remove = list(val.values())[0]
self.remove_spend(to_remove)

self.spends[item.name] = item
Expand Down
1 change: 0 additions & 1 deletion src/mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ async def check_removals(
removal, mempool.header.height + 1, uint32(0), False, False
)
continue
log.warning(f"Getting removal {removal}")
# 2. Checks we have it in the unspent_store
unspent: Optional[CoinRecord] = await self.unspent_store.get_coin_record(
removal.name(), mempool.header
Expand Down
4 changes: 3 additions & 1 deletion tests/setup_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"DIFFICULTY_DELAY": 3, # EPOCH / WARP_FACTOR
"PROPAGATION_THRESHOLD": 10,
"PROPAGATION_DELAY_THRESHOLD": 20,
"TX_PER_SEC": 1,
"MEMPOOL_BLOCK_BUFFER": 10,
}
test_constants["GENESIS_BLOCK"] = bytes(
bt.create_genesis_block(test_constants, bytes([0] * 32), b"0")
Expand All @@ -51,7 +53,7 @@ async def setup_full_node(db_name, port, introducer_port=None, dic={}):
await store_1._clear_database()
unspent_store_1 = await CoinStore.create(Path(db_name))
await unspent_store_1._clear_database()
mempool_1 = MempoolManager(unspent_store_1, dic)
mempool_1 = MempoolManager(unspent_store_1, test_constants_copy)

b_1: Blockchain = await Blockchain.create(
unspent_store_1, store_1, test_constants_copy
Expand Down
116 changes: 86 additions & 30 deletions tests/test_full_node.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import asyncio
import pytest
from clvm.casts import int_to_bytes
import random
from typing import Dict
from secrets import token_bytes

from src.protocols import full_node_protocol as fnp
from src.types.peer_info import PeerInfo
from src.util.bundle_tools import best_solution_program
from src.util.ints import uint16, uint32, uint64
from src.types.ConditionVarPair import ConditionVarPair
from src.types.condition_opcodes import ConditionOpcode
from tests.setup_nodes import setup_two_nodes, test_constants, bt
from tests.wallet_tools import WalletTool


num_blocks = 5


@pytest.fixture(scope="module")
def event_loop():
loop = asyncio.get_event_loop()
Expand All @@ -16,13 +26,12 @@ def event_loop():

@pytest.fixture(scope="module")
async def two_nodes():
async for _ in setup_two_nodes():
async for _ in setup_two_nodes({"COINBASE_FREEZE_PERIOD": 0}):
yield _


@pytest.fixture(scope="module")
def wallet_blocks():
num_blocks = 3
wallet_a = WalletTool()
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
wallet_receiver = WalletTool()
Expand All @@ -38,7 +47,7 @@ async def test_new_tip(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
_, _, blocks = wallet_blocks

for i in range(1, 3):
for i in range(1, num_blocks):
async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks[i])):
pass

Expand All @@ -54,49 +63,96 @@ async def test_new_tip(self, two_nodes, wallet_blocks):

assert len(msgs_1) == 1
assert msgs_1[0].message.data == fnp.RequestBlock(
uint32(3), blocks[-1].header_hash
uint32(num_blocks), blocks[-1].header_hash
)

new_tip_2 = fnp.NewTip(
blocks[-2].height, blocks[-2].weight, blocks[-2].header_hash
blocks[3].height, blocks[3].weight, blocks[3].header_hash
)
msgs_2 = [x async for x in full_node_1.new_tip(new_tip_2)]
assert len(msgs_2) == 0

@pytest.mark.asyncio
async def test_new_transaction(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes

wallet_a, wallet_receiver, blocks = wallet_blocks
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
spent_block = blocks[1]
conditions_dict: Dict = {ConditionOpcode.CREATE_COIN: []}

# Mempool has capacity of 100, make 110 unspents that we can use
puzzle_hashes = []
for _ in range(110):
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
puzzle_hashes.append(receiver_puzzlehash)
output = ConditionVarPair(
ConditionOpcode.CREATE_COIN, receiver_puzzlehash, int_to_bytes(1000)
)
conditions_dict[ConditionOpcode.CREATE_COIN].append(output)

spend_bundle = wallet_a.generate_signed_transaction(
1001, receiver_puzzlehash, spent_block.body.coinbase
100,
receiver_puzzlehash,
blocks[1].body.coinbase,
condition_dic=conditions_dict,
)
assert spend_bundle is not None

tx_id_1 = spend_bundle.get_hash()
new_transaction_1 = fnp.NewTransaction(tx_id_1, uint64(100), uint64(100))
new_transaction = fnp.NewTransaction(
spend_bundle.get_hash(), uint64(100), uint64(100)
)
# Not seen
msgs_1 = [x async for x in full_node_1.new_transaction(new_transaction_1)]
assert len(msgs_1) == 1
assert msgs_1[0].message.data == fnp.RequestTransaction(tx_id_1)
msgs = [x async for x in full_node_1.new_transaction(new_transaction)]
assert len(msgs) == 1
assert msgs[0].message.data == fnp.RequestTransaction(spend_bundle.get_hash())

respond_transaction_2 = fnp.RespondTransaction(spend_bundle)
[x async for x in full_node_1.respond_transaction(respond_transaction_2)]

program = best_solution_program(spend_bundle)
aggsig = spend_bundle.aggregated_signature

dic_h = {5: (program, aggsig)}
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
blocks_new = bt.get_consecutive_blocks(
test_constants,
1,
blocks[:-1],
10,
reward_puzzlehash=coinbase_puzzlehash,
transaction_data_at_height=dic_h,
)
# Already seen
msgs = [x async for x in full_node_1.new_transaction(new_transaction)]
assert len(msgs) == 0

# Farm one block
[_ async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks_new[-1]))]

# Fill mempool
for puzzle_hash in puzzle_hashes:
coin_record = (
await full_node_1.unspent_store.get_coin_records_by_puzzle_hash(
puzzle_hash, blocks_new[-1].header
)
)[0]
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
spend_bundle = wallet_receiver.generate_signed_transaction(
500, receiver_puzzlehash, coin_record.coin, fee=random.randint(0, 499)
)
respond_transaction = fnp.RespondTransaction(spend_bundle)
[x async for x in full_node_1.respond_transaction(respond_transaction)]

# Mempool is full
new_transaction = fnp.NewTransaction(token_bytes(32), uint64(10000), uint64(1))
msgs = [x async for x in full_node_1.new_transaction(new_transaction)]
assert len(msgs) == 0

respond_transaction_1 = fnp.RespondTransaction(spend_bundle)
[x async for x in full_node_1.respond_transaction(respond_transaction_1)]
@pytest.mark.asyncio
async def test_request_transaction(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks

# Already seen
msgs_3 = [x async for x in full_node_1.new_transaction(new_transaction_1)]
assert len(msgs_3) == 0

# for _ in range(10):
# spend_bundle = wallet_a.generate_signed_transaction(
# 1001, receiver_puzzlehash, spent_block.body.coinbase
# )
# assert spend_bundle is not None
# new_transaction_1 = fnp.NewTransaction(
# spend_bundle.get_hash(), uint64(100), uint64(100)
# )
# respond_transaction_2 = fnp.RespondTransaction(spend_bundle)
# [x async for x in full_node_1.respond_transaction(respond_transaction_2)]
tx_id = token_bytes(32)
request_transaction = fnp.RequestTransaction(tx_id)
msgs = [x async for x in full_node_1.request_transaction(request_transaction)]
assert len(msgs) == 1
assert msgs[0].message.data == fnp.RejectTransactionRequest(tx_id)
13 changes: 10 additions & 3 deletions tests/wallet_tools.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List, Optional, Dict, Tuple

import clvm
from clvm.casts import int_to_bytes, int_from_bytes
from os import urandom
from blspy import ExtendedPrivateKey

Expand Down Expand Up @@ -131,19 +132,25 @@ def generate_unsigned_transaction(
):
spends = []
spend_value = coin.amount
change = spend_value - amount - fee
puzzle_hash = coin.puzzle_hash
pubkey, secretkey = self.get_keys(puzzle_hash)
puzzle = puzzle_for_pk(pubkey.serialize())
if ConditionOpcode.CREATE_COIN not in condition_dic:
condition_dic[ConditionOpcode.CREATE_COIN] = []

output = ConditionVarPair(ConditionOpcode.CREATE_COIN, newpuzzlehash, amount)
output = ConditionVarPair(
ConditionOpcode.CREATE_COIN, newpuzzlehash, int_to_bytes(amount)
)
condition_dic[output.opcode].append(output)
amount_total = sum(
int_from_bytes(cvp.var2)
for cvp in condition_dic[ConditionOpcode.CREATE_COIN]
)
change = spend_value - amount_total - fee
if change > 0:
changepuzzlehash = self.get_new_puzzlehash()
change_output = ConditionVarPair(
ConditionOpcode.CREATE_COIN, changepuzzlehash, change
ConditionOpcode.CREATE_COIN, changepuzzlehash, int_to_bytes(change)
)
condition_dic[output.opcode].append(change_output)
solution = self.make_solution(condition_dic)
Expand Down

0 comments on commit 3250f1f

Please sign in to comment.