More full node tests

This commit is contained in:
Mariano Sorgente 2020-02-24 17:14:48 +09:00
parent 4b98c3706d
commit c90aa0984d
No known key found for this signature in database
GPG Key ID: 0F866338C369278C
4 changed files with 292 additions and 32 deletions

View File

@ -752,8 +752,6 @@ class FullNode:
A proof of time, received by a peer full node. If we have the rest of the block,
we can complete it. Otherwise, we just verify and propagate the proof.
"""
finish_block: bool = False
propagate_proof: bool = False
if (
self.store.get_unfinished_block(
(
@ -763,33 +761,26 @@ class FullNode:
)
is not None
):
finish_block = True
elif respond_proof_of_time.proof.is_valid(constants["DISCRIMINANT_SIZE_BITS"]):
propagate_proof = True
if finish_block or propagate_proof:
height: Optional[uint32] = self.store.get_proof_of_time_heights(
(
respond_proof_of_time.proof.challenge_hash,
respond_proof_of_time.proof.number_of_iterations,
)
)
if height is None:
return
yield OutboundMessage(
NodeType.FULL_NODE,
Message(
"new_proof_of_time",
full_node_protocol.NewProofOfTime(
height,
respond_proof_of_time.proof.challenge_hash,
respond_proof_of_time.proof.number_of_iterations,
if height is not None:
yield OutboundMessage(
NodeType.FULL_NODE,
Message(
"new_proof_of_time",
full_node_protocol.NewProofOfTime(
height,
respond_proof_of_time.proof.challenge_hash,
respond_proof_of_time.proof.number_of_iterations,
),
),
),
Delivery.BROADCAST_TO_OTHERS,
)
Delivery.BROADCAST_TO_OTHERS,
)
if finish_block:
request = timelord_protocol.ProofOfTimeFinished(respond_proof_of_time.proof)
async for msg in self.proof_of_time_finished(request):
yield msg
@ -931,13 +922,23 @@ class FullNode:
)
if prev_block is not None:
challenge = self.blockchain.get_challenge(prev_block)
if (
self.store.get_unfinished_block(
(challenge, self.new_unfinished_block.iterations_needed)
)
is not None
):
return
if challenge is not None:
if (
self.store.get_unfinished_block(
(
challenge.get_hash(),
new_unfinished_block.number_of_iterations,
)
)
is not None
):
return
assert challenge is not None
print(self.store.unfinished_blocks.keys())
print(
"It's none..",
(challenge.get_hash(), new_unfinished_block.number_of_iterations),
)
yield OutboundMessage(
NodeType.FULL_NODE,
Message(

View File

@ -82,7 +82,7 @@ class RespondProofOfTime:
@cbor_message
class RejectProofOfTimeRequest:
challenge_hash: bytes32
iterations: uint64
number_of_iterations: uint64
@dataclass(frozen=True)
@ -111,14 +111,14 @@ class RespondCompactProofOfTime:
@cbor_message
class RejectCompactProofOfTimeRequest:
challenge_hash: bytes32
iterations: uint64
number_of_iterations: uint64
@dataclass(frozen=True)
@cbor_message
class NewUnfinishedBlock:
previous_header_hash: bytes32
iterations: uint64
number_of_iterations: uint64
new_header_hash: bytes32

View File

@ -7,6 +7,7 @@ from secrets import token_bytes
from src.protocols import full_node_protocol as fnp
from src.types.peer_info import PeerInfo
from src.types.full_block import FullBlock
from src.types.hashable.SpendBundle import SpendBundle
from src.util.bundle_tools import best_solution_program
from src.util.ints import uint16, uint32, uint64
@ -234,3 +235,261 @@ class TestFullNode:
async def test_new_pot(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks
no_unf_block = fnp.NewProofOfTime(uint32(5), bytes(32 * [1]), uint64(124512))
assert len([x async for x in full_node_1.new_proof_of_time(no_unf_block)]) == 0
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
blocks_new = bt.get_consecutive_blocks(
test_constants,
1,
blocks[:-1],
10,
reward_puzzlehash=coinbase_puzzlehash,
seed=b"1212412",
)
unf_block = FullBlock(
blocks_new[-1].proof_of_space,
None,
blocks_new[-1].header,
blocks_new[-1].body,
)
unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
res = [x async for x in full_node_1.respond_unfinished_block(unf_block_req)]
dont_have = fnp.NewProofOfTime(
unf_block.height,
unf_block.proof_of_space.challenge_hash,
res[0].message.data.iterations_needed,
)
assert len([x async for x in full_node_1.new_proof_of_time(dont_have)]) == 1
[x async for x in full_node_1.respond_block(fnp.RespondBlock(blocks_new[-1]))]
already_have = fnp.NewProofOfTime(
unf_block.height,
unf_block.proof_of_space.challenge_hash,
res[0].message.data.iterations_needed,
)
assert len([x async for x in full_node_1.new_proof_of_time(already_have)]) == 0
@pytest.mark.asyncio
async def test_request_pot(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks
request = fnp.RequestProofOfTime(
blocks[3].height,
blocks[3].proof_of_space.challenge_hash,
blocks[3].proof_of_time.number_of_iterations,
)
res = [x async for x in full_node_1.request_proof_of_time(request)]
assert len(res) == 1
assert res[0].message.data.proof == blocks[3].proof_of_time
request_bad = fnp.RequestProofOfTime(
blocks[3].height,
blocks[3].proof_of_space.challenge_hash,
blocks[3].proof_of_time.number_of_iterations + 1,
)
res_bad = [x async for x in full_node_1.request_proof_of_time(request_bad)]
assert len(res_bad) == 1
assert isinstance(res_bad[0].message.data, fnp.RejectProofOfTimeRequest)
@pytest.mark.asyncio
async def test_respond_pot(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
blocks_list = [(await full_node_1.blockchain.get_full_tips())[0]]
while blocks_list[0].height != 0:
b = await full_node_1.store.get_block(blocks_list[0].prev_header_hash)
blocks_list.insert(0, b)
blocks_new = bt.get_consecutive_blocks(
test_constants,
1,
blocks_list,
10,
reward_puzzlehash=coinbase_puzzlehash,
seed=b"another seed",
)
assert blocks_new[-1].proof_of_time is not None
new_pot = fnp.NewProofOfTime(
blocks_new[-1].height,
blocks_new[-1].proof_of_space.challenge_hash,
blocks_new[-1].proof_of_time.number_of_iterations,
)
[x async for x in full_node_1.new_proof_of_time(new_pot)]
# Don't have unfinished block
respond_pot = fnp.RespondProofOfTime(blocks_new[-1].proof_of_time)
res = [x async for x in full_node_1.respond_proof_of_time(respond_pot)]
assert len(res) == 0
unf_block = FullBlock(
blocks_new[-1].proof_of_space,
None,
blocks_new[-1].header,
blocks_new[-1].body,
)
unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
[x async for x in full_node_1.respond_unfinished_block(unf_block_req)]
# Have unfinished block, finish
assert blocks_new[-1].proof_of_time is not None
respond_pot = fnp.RespondProofOfTime(blocks_new[-1].proof_of_time)
res = [x async for x in full_node_1.respond_proof_of_time(respond_pot)]
assert len(res) == 4
@pytest.mark.asyncio
async def test_new_unfinished(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
blocks_list = [(await full_node_1.blockchain.get_full_tips())[0]]
while blocks_list[0].height != 0:
b = await full_node_1.store.get_block(blocks_list[0].prev_header_hash)
blocks_list.insert(0, b)
blocks_new = bt.get_consecutive_blocks(
test_constants,
1,
blocks_list,
10,
reward_puzzlehash=coinbase_puzzlehash,
seed=b"another seed 2",
)
assert blocks_new[-1].proof_of_time is not None
assert blocks_new[-2].proof_of_time is not None
already_have = fnp.NewUnfinishedBlock(
blocks_new[-2].prev_header_hash,
blocks_new[-2].proof_of_time.number_of_iterations,
blocks_new[-2].header_hash,
)
assert (
len([x async for x in full_node_1.new_unfinished_block(already_have)]) == 0
)
bad_prev = fnp.NewUnfinishedBlock(
blocks_new[-1].header_hash,
blocks_new[-1].proof_of_time.number_of_iterations,
blocks_new[-1].header_hash,
)
assert len([x async for x in full_node_1.new_unfinished_block(bad_prev)]) == 0
good = fnp.NewUnfinishedBlock(
blocks_new[-1].prev_header_hash,
blocks_new[-1].proof_of_time.number_of_iterations,
blocks_new[-1].header_hash,
)
assert len([x async for x in full_node_1.new_unfinished_block(good)]) == 1
unf_block = FullBlock(
blocks_new[-1].proof_of_space,
None,
blocks_new[-1].header,
blocks_new[-1].body,
)
unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
[x async for x in full_node_1.respond_unfinished_block(unf_block_req)]
assert len([x async for x in full_node_1.new_unfinished_block(good)]) == 0
@pytest.mark.asyncio
async def test_request_unfinished(self, two_nodes, wallet_blocks):
full_node_1, full_node_2, server_1, server_2 = two_nodes
wallet_a, wallet_receiver, blocks = wallet_blocks
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
blocks_list = [(await full_node_1.blockchain.get_full_tips())[0]]
while blocks_list[0].height != 0:
b = await full_node_1.store.get_block(blocks_list[0].prev_header_hash)
blocks_list.insert(0, b)
blocks_new = bt.get_consecutive_blocks(
test_constants,
1,
blocks_list,
10,
reward_puzzlehash=coinbase_puzzlehash,
seed=b"another seed 3",
)
unf_block = FullBlock(
blocks_new[-1].proof_of_space,
None,
blocks_new[-1].header,
blocks_new[-1].body,
)
unf_block_req = fnp.RespondUnfinishedBlock(unf_block)
# Don't have
req = fnp.RequestUnfinishedBlock(unf_block.header_hash)
res = [x async for x in full_node_1.request_unfinished_block(req)]
assert len(res) == 1
assert res[0].message.data == fnp.RejectUnfinishedBlockRequest(
unf_block.header_hash
)
# Have unfinished block
[x async for x in full_node_1.respond_unfinished_block(unf_block_req)]
res = [x async for x in full_node_1.request_unfinished_block(req)]
assert len(res) == 1
assert res[0].message.data == fnp.RespondUnfinishedBlock(unf_block)
# Have full block (genesis in this case)
req = fnp.RequestUnfinishedBlock(blocks_new[0].header_hash)
res = [x async for x in full_node_1.request_unfinished_block(req)]
assert len(res) == 1
assert res[0].message.data.block.header_hash == blocks_new[0].header_hash
# @pytest.mark.asyncio
# async def test_respond_unfinished(self, two_nodes, wallet_blocks):
# full_node_1, full_node_2, server_1, server_2 = two_nodes
# wallet_a, wallet_receiver, blocks = wallet_blocks
# coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
# blocks_list = [(await full_node_1.blockchain.get_full_tips())[0]]
# while blocks_list[0].height != 0:
# b = await full_node_1.store.get_block(blocks_list[0].prev_header_hash)
# blocks_list.insert(0, b)
# candidates = []
# for i in range(50):
# blocks_new = bt.get_consecutive_blocks(
# test_constants,
# 1,
# blocks_list,
# 10,
# reward_puzzlehash=coinbase_puzzlehash,
# seed=b"another seed 4",
# )
# candidates.append(blocks_new[-1])
# print([c.proof_of_time.number_of_iterations for c in candidates])
# unf_block = FullBlock(
# candidates[0].proof_of_space,
# None,
# candidates[0].header,
# candidates[0].body,
# )
# unf_block_not_child = FullBlock(
# candidates[0].proof_of_space,
# None,
# candidates[0].header,
# candidates[0].body,
# )
# unf_block_req_bad = fnp.RespondUnfinishedBlock(unf_block_not_child)
# assert len([x async for x in full_node_1.respond_unfinished_block(unf_block_req_bad)]) == 0
# Already seen
# Slow block should delay prop
# Highest height should propagate
# Slow equal height should not
# Fastest equal height should
# Don't propagate at old height

View File

@ -43,7 +43,7 @@ class WalletTool:
self.extended_secret_key = ExtendedPrivateKey.from_seed(self.seed)
self.generator_lookups: Dict = {}
self.name = "MyChiaWallet"
self.puzzle_pk_cache = {}
self.puzzle_pk_cache: Dict = {}
def get_next_public_key(self):
pubkey = self.extended_secret_key.public_child(