__bytes__, cbor, etc
This commit is contained in:
parent
85b1b04173
commit
e65d9bad71
|
@ -26,7 +26,7 @@ python -m src.server.start_plotter
|
|||
python -m src.server.start_timelord
|
||||
python -m src.server.start_farmer
|
||||
python -m src.server.start_full_node "127.0.0.1" 8002 -f
|
||||
python -m src.server.start_full_node "127.0.0.1" 8004 -t -u
|
||||
python -m src.server.start_full_node "127.0.0.1" 8004 -t -u 8222
|
||||
python -m src.server.start_full_node "127.0.0.1" 8005
|
||||
|
||||
```
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
asyncssh==2.0.0
|
||||
atomicwrites==1.3.0
|
||||
attrs==19.3.0
|
||||
bitstring==3.1.6
|
||||
blspy==0.1.11
|
||||
cbor2==4.1.2
|
||||
cffi==1.13.1
|
||||
cppimport==18.11.8
|
||||
cryptography==2.8
|
||||
entrypoints==0.3
|
||||
flake8==3.7.9
|
||||
importlib-metadata==0.23
|
||||
Mako==1.1.0
|
||||
MarkupSafe==1.1.1
|
||||
mccabe==0.6.1
|
||||
more-itertools==7.2.0
|
||||
mypy==0.740
|
||||
|
@ -12,7 +19,9 @@ mypy-extensions==0.4.3
|
|||
packaging==19.2
|
||||
pluggy==0.13.0
|
||||
py==1.8.0
|
||||
pybind11==2.4.3
|
||||
pycodestyle==2.5.0
|
||||
pycparser==2.19
|
||||
pyflakes==2.1.1
|
||||
pyparsing==2.4.2
|
||||
pytest==5.2.2
|
||||
|
|
|
@ -405,7 +405,7 @@ class Blockchain:
|
|||
return False
|
||||
|
||||
# 11. Check coinbase signature with pool pk
|
||||
if not block.body.coinbase_signature.verify([blspy.Util.hash256(block.body.coinbase.serialize())],
|
||||
if not block.body.coinbase_signature.verify([blspy.Util.hash256(bytes(block.body.coinbase))],
|
||||
[block.trunk_block.proof_of_space.pool_pubkey]):
|
||||
return False
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ pool_sks:
|
|||
# sha256(PrivateKey.from_seed(b'0').get_public_key().serialize()).digest()
|
||||
pool_target: "9940b95222a1d19abb73c192f2c10dc65b32bcc7a703db1b40456f2dbf1e416e"
|
||||
|
||||
pool_share_threshold: 500 # To send to pool, must be expected to take less than these seconds
|
||||
propagate_threshold: 400 # To propagate to network, must be expected to take less than these seconds
|
||||
pool_share_threshold: 1500 # To send to pool, must be expected to take less than these seconds
|
||||
propagate_threshold: 1000 # To propagate to network, must be expected to take less than these seconds
|
||||
|
||||
plotter_peer:
|
||||
host: "127.0.0.1"
|
||||
|
|
|
@ -11,8 +11,6 @@ short_sync_download_count: 6
|
|||
host: "127.0.0.1"
|
||||
port: 8002
|
||||
|
||||
# SSH server started, for UI
|
||||
ssh_port: 8222
|
||||
ssh_filename: "src/config/ssh_host_key"
|
||||
|
||||
farmer_peer:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,7 +6,7 @@ from bson.codec_options import CodecOptions
|
|||
|
||||
def fallback_encoder(obj):
|
||||
if isinstance(obj, Streamable):
|
||||
return Binary(obj.serialize())
|
||||
return Binary(bytes(obj))
|
||||
return obj
|
||||
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ class Farmer:
|
|||
|
||||
pool_sks: List[PrivateKey] = [PrivateKey.from_bytes(bytes.fromhex(ce))
|
||||
for ce in self.config["pool_sks"]]
|
||||
coinbase_signature: PrependSignature = pool_sks[0].sign_prepend(coinbase.serialize())
|
||||
coinbase_signature: PrependSignature = pool_sks[0].sign_prepend(bytes(coinbase))
|
||||
self.coinbase_rewards[uint32(self.current_height + 1)] = (coinbase, coinbase_signature)
|
||||
|
||||
log.info(f"\tCurrent height set to {self.current_height}")
|
||||
|
|
|
@ -295,6 +295,7 @@ class ChiaServer:
|
|||
try:
|
||||
f = getattr(api, full_message.function)
|
||||
if f is not None:
|
||||
log.info(f"<- {f.__name__} from peer {connection.get_peername()}")
|
||||
result = f(full_message.data)
|
||||
if isinstance(result, AsyncGenerator):
|
||||
async for outbound_message in result:
|
||||
|
|
|
@ -50,8 +50,10 @@ async def main():
|
|||
log.info("Server closed.")
|
||||
|
||||
if "-u" in sys.argv:
|
||||
index = sys.argv.index("-u")
|
||||
ui_ssh_port = int(sys.argv[index + 1])
|
||||
from src.ui.prompt_ui import FullNodeUI
|
||||
ui = FullNodeUI(store, blockchain, server.global_connections, port, full_node.config['ssh_port'],
|
||||
ui = FullNodeUI(store, blockchain, server.global_connections, port, ui_ssh_port,
|
||||
full_node.config['ssh_filename'], master_close_cb)
|
||||
|
||||
connect_to_farmer = ("-f" in sys.argv)
|
||||
|
@ -64,9 +66,9 @@ async def main():
|
|||
NodeType.FULL_NODE, full_node.on_connect))
|
||||
await asyncio.gather(*peer_tasks)
|
||||
|
||||
log.info("Waiting to perform handshake with all peers...")
|
||||
# TODO: have a cleaner way to wait for all the handshakes
|
||||
log.info("Waiting to connect to some peers...")
|
||||
await asyncio.sleep(3)
|
||||
|
||||
if server_closed:
|
||||
return
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ python -m src.server.start_farmer &
|
|||
P3=$!
|
||||
python -m src.server.start_full_node "127.0.0.1" 8002 -f &
|
||||
P4=$!
|
||||
python -m src.server.start_full_node "127.0.0.1" 8004 -t -u &
|
||||
python -m src.server.start_full_node "127.0.0.1" 8004 -t -u 8222 &
|
||||
P5=$!
|
||||
python -m src.server.start_full_node "127.0.0.1" 8005 &
|
||||
P6=$!
|
||||
|
|
|
@ -62,7 +62,6 @@ class Timelord:
|
|||
log.info(f"Will not execute challenge at height {challenge_start}, too old")
|
||||
return
|
||||
assert(len(self.active_heights) > 0)
|
||||
log.info(f"{challenge_start.height}, max is {max(self.active_heights)}")
|
||||
if (challenge_start.height == max(self.active_heights)):
|
||||
if (len(self.free_servers) != 0):
|
||||
port = self.free_servers[0]
|
||||
|
@ -120,15 +119,10 @@ class Timelord:
|
|||
log.info("Stopped server")
|
||||
# Server is now available.
|
||||
async with self.lock:
|
||||
log.info("Acquired lock for writing")
|
||||
writer.write(b"ACK")
|
||||
log.info("Wrote ack to server")
|
||||
await writer.drain()
|
||||
log.info("Drained VDF server")
|
||||
await proc.wait()
|
||||
log.info("Waited for process to exit")
|
||||
self.free_servers.append(port)
|
||||
log.info(f"Appended {port} to free ports")
|
||||
if challenge_start.challenge_hash in self.active_discriminants:
|
||||
del self.active_discriminants[challenge_start.challenge_hash]
|
||||
del self.active_discriminants_start_time[challenge_start.challenge_hash]
|
||||
|
|
|
@ -26,6 +26,5 @@ def api_request(f):
|
|||
if param_name != "return" and isinstance(inter[param_name], dict):
|
||||
inter[param_name] = param_class(**inter[param_name])
|
||||
|
||||
log.info(f"<- {f.__name__}")
|
||||
return f(**inter)
|
||||
return f_substitute
|
||||
|
|
|
@ -29,7 +29,7 @@ def make_sized_bytes(size):
|
|||
f = io.BytesIO(blob)
|
||||
return cls.parse(f)
|
||||
|
||||
def serialize(self: Any) -> bytes:
|
||||
def __bytes__(self: Any) -> bytes:
|
||||
f = io.BytesIO()
|
||||
self.stream(f)
|
||||
return bytes(f.getvalue())
|
||||
|
@ -41,6 +41,6 @@ def make_sized_bytes(size):
|
|||
return "<%s: %s>" % (self.__class__.__name__, str(self))
|
||||
|
||||
namespace = dict(__new__=__new__, parse=parse, stream=stream, from_bytes=from_bytes,
|
||||
serialize=serialize, __str__=__str__, __repr__=__repr__)
|
||||
__bytes__=__bytes__, __str__=__str__, __repr__=__repr__)
|
||||
|
||||
return type(name, (bytes,), namespace)
|
||||
|
|
|
@ -19,7 +19,10 @@ def default_encoder(encoder, value: Any):
|
|||
fields: Dict = get_type_hints(value)
|
||||
els = {f_name: getattr(value, f_name) for f_name in fields.keys()}
|
||||
encoder.encode(els)
|
||||
elif hasattr(type(value), "__bytes__"):
|
||||
encoder.encode(bytes(value))
|
||||
elif hasattr(type(value), "serialize"):
|
||||
# Useful for blspy objects
|
||||
encoder.encode(value.serialize())
|
||||
else:
|
||||
raise NotImplementedError(f"can't CBOR encode {type(value)}:{value}")
|
||||
|
|
|
@ -98,7 +98,10 @@ class Streamable:
|
|||
self.stream_one_item(inner_type, item, f)
|
||||
elif hasattr(f_type, "stream"):
|
||||
item.stream(f)
|
||||
elif hasattr(f_type, "__bytes__"):
|
||||
f.write(bytes(item))
|
||||
elif hasattr(f_type, "serialize"):
|
||||
# Useful for blspy objects
|
||||
f.write(item.serialize())
|
||||
else:
|
||||
raise NotImplementedError(f"can't stream {item}, {f_type}")
|
||||
|
@ -108,14 +111,14 @@ class Streamable:
|
|||
self.stream_one_item(f_type, getattr(self, f_name), f)
|
||||
|
||||
def get_hash(self) -> bytes32:
|
||||
return bytes32(sha256(self.serialize()).digest())
|
||||
return bytes32(sha256(bytes(self)).digest())
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls: Any, blob: bytes) -> Any:
|
||||
f = io.BytesIO(blob)
|
||||
return cls.parse(f)
|
||||
|
||||
def serialize(self: Any) -> bytes:
|
||||
def __bytes__(self: Any) -> bytes:
|
||||
f = io.BytesIO()
|
||||
self.stream(f)
|
||||
return bytes(f.getvalue())
|
||||
|
|
|
@ -31,7 +31,7 @@ class StructStream(int):
|
|||
f = io.BytesIO(blob)
|
||||
return cls.parse(f)
|
||||
|
||||
def serialize(self: Any) -> bytes:
|
||||
def __bytes__(self: Any) -> bytes:
|
||||
f = io.BytesIO()
|
||||
self.stream(f)
|
||||
return bytes(f.getvalue())
|
||||
|
|
|
@ -69,7 +69,7 @@ class BlockTools:
|
|||
num_blocks: int,
|
||||
block_list: List[FullBlock] = [],
|
||||
seconds_per_block=constants["BLOCK_TIME_TARGET"],
|
||||
seed: uint64 = uint64(0)) -> List[FullBlock]:
|
||||
seed: bytes = b'') -> List[FullBlock]:
|
||||
test_constants: Dict[str, Any] = constants.copy()
|
||||
for key, value in input_constants.items():
|
||||
test_constants[key] = value
|
||||
|
@ -78,7 +78,7 @@ class BlockTools:
|
|||
if "GENESIS_BLOCK" in test_constants:
|
||||
block_list.append(FullBlock.from_bytes(test_constants["GENESIS_BLOCK"]))
|
||||
else:
|
||||
block_list.append(self.create_genesis_block(test_constants, bytes([(seed) % 256]*32), seed))
|
||||
block_list.append(self.create_genesis_block(test_constants, sha256(seed).digest(), seed))
|
||||
prev_difficulty = test_constants["DIFFICULTY_STARTING"]
|
||||
curr_difficulty = prev_difficulty
|
||||
curr_ips = test_constants["VDF_IPS_STARTING"]
|
||||
|
@ -162,7 +162,7 @@ class BlockTools:
|
|||
return block_list
|
||||
|
||||
def create_genesis_block(self, input_constants: Dict, challenge_hash=bytes([0]*32),
|
||||
seed: uint64 = uint64(0)) -> FullBlock:
|
||||
seed: bytes = b'') -> FullBlock:
|
||||
"""
|
||||
Creates the genesis block with the specified details.
|
||||
"""
|
||||
|
@ -185,7 +185,7 @@ class BlockTools:
|
|||
|
||||
def create_next_block(self, input_constants: Dict, prev_block: FullBlock, timestamp: uint64,
|
||||
difficulty: uint64, ips: uint64,
|
||||
seed: int = 0) -> FullBlock:
|
||||
seed: bytes = b'') -> FullBlock:
|
||||
"""
|
||||
Creates the next block with the specified details.
|
||||
"""
|
||||
|
@ -210,7 +210,7 @@ class BlockTools:
|
|||
|
||||
def _create_block(self, test_constants: Dict, challenge_hash: bytes32, height: uint32, prev_header_hash: bytes32,
|
||||
prev_iters: uint64, prev_weight: uint64, timestamp: uint64, difficulty: uint64,
|
||||
ips: uint64, seed: int) -> FullBlock:
|
||||
ips: uint64, seed: bytes) -> FullBlock:
|
||||
"""
|
||||
Creates a block with the specified details. Uses the stored plots to create a proof of space,
|
||||
and also evaluates the VDF for the proof of time.
|
||||
|
@ -220,7 +220,8 @@ class BlockTools:
|
|||
plot_sk = None
|
||||
qualities: List[bytes] = []
|
||||
for pn in range(num_plots):
|
||||
seeded_pn = (pn + 17 * seed) % num_plots # Allow passing in seed, to create reorgs and different chains
|
||||
# Allow passing in seed, to create reorgs and different chains
|
||||
seeded_pn = (pn + 17 * int.from_bytes(seed, "big")) % num_plots
|
||||
filename = self.filenames[seeded_pn]
|
||||
plot_pk = plot_pks[seeded_pn]
|
||||
plot_sk = plot_sks[seeded_pn]
|
||||
|
@ -253,11 +254,12 @@ class BlockTools:
|
|||
|
||||
coinbase: CoinbaseInfo = CoinbaseInfo(height, block_rewards.calculate_block_reward(uint32(height)),
|
||||
coinbase_target)
|
||||
coinbase_sig: PrependSignature = pool_sk.sign_prepend(coinbase.serialize())
|
||||
coinbase_sig: PrependSignature = pool_sk.sign_prepend(bytes(coinbase))
|
||||
|
||||
fees_target: FeesTarget = FeesTarget(fee_target, uint64(0))
|
||||
|
||||
body: BlockBody = BlockBody(coinbase, coinbase_sig, fees_target, None, bytes([0]*32))
|
||||
solutions_generator: bytes32 = sha256(seed).digest()
|
||||
body: BlockBody = BlockBody(coinbase, coinbase_sig, fees_target, None, solutions_generator)
|
||||
|
||||
header_data: BlockHeaderData = BlockHeaderData(prev_header_hash, timestamp, bytes([0]*32),
|
||||
proof_of_space.get_hash(), body.get_hash(),
|
||||
|
@ -279,5 +281,5 @@ class BlockTools:
|
|||
# This code generates a genesis block, uncomment to output genesis block to terminal
|
||||
# This might take a while, using the python VDF implementation.
|
||||
# Run by doing python -m tests.block_tools
|
||||
# bt = BlockTools()
|
||||
# print(bt.create_genesis_block({}, bytes([1]*32), uint64(0)).serialize())
|
||||
bt = BlockTools()
|
||||
print(bytes(bt.create_genesis_block({}, bytes([1]*32), b'0')))
|
||||
|
|
|
@ -29,7 +29,7 @@ test_constants: Dict[str, Any] = {
|
|||
"DIFFICULTY_WARP_FACTOR": 4, # DELAY divides EPOCH in order to warp efficiently.
|
||||
"DIFFICULTY_DELAY": 3 # EPOCH / WARP_FACTOR
|
||||
}
|
||||
test_constants["GENESIS_BLOCK"] = bt.create_genesis_block(test_constants, bytes([0]*32), uint64(0)).serialize()
|
||||
test_constants["GENESIS_BLOCK"] = bytes(bt.create_genesis_block(test_constants, bytes([0]*32), b'0'))
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
@ -236,7 +236,7 @@ class TestReorgs():
|
|||
await b.receive_block(block)
|
||||
assert b.get_current_heads()[0].height == 100
|
||||
|
||||
blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 30, blocks[:90], 9, uint64(1))
|
||||
blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 30, blocks[:90], 9, b'1')
|
||||
for reorg_block in blocks_reorg_chain:
|
||||
result = await b.receive_block(reorg_block)
|
||||
if reorg_block.height < 90:
|
||||
|
@ -249,7 +249,7 @@ class TestReorgs():
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_reorg_from_genesis(self):
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 20, [], 9, uint64(0))
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 20, [], 9, b'0')
|
||||
store = FullNodeStore()
|
||||
await store.initialize()
|
||||
b: Blockchain = Blockchain(store, test_constants)
|
||||
|
@ -259,7 +259,7 @@ class TestReorgs():
|
|||
assert b.get_current_heads()[0].height == 20
|
||||
|
||||
# Reorg from genesis
|
||||
blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 21, [blocks[0]], 9, uint64(1))
|
||||
blocks_reorg_chain = bt.get_consecutive_blocks(test_constants, 21, [blocks[0]], 9, b'1')
|
||||
for reorg_block in blocks_reorg_chain:
|
||||
result = await b.receive_block(reorg_block)
|
||||
if reorg_block.height == 0:
|
||||
|
@ -271,32 +271,31 @@ class TestReorgs():
|
|||
assert b.get_current_heads()[0].height == 21
|
||||
|
||||
# Reorg back to original branch
|
||||
blocks_reorg_chain_2 = bt.get_consecutive_blocks(test_constants, 3, blocks, 9, uint64(3))
|
||||
blocks_reorg_chain_2 = bt.get_consecutive_blocks(test_constants, 3, blocks, 9, b'3')
|
||||
await b.receive_block(blocks_reorg_chain_2[20]) == ReceiveBlockResult.ADDED_AS_ORPHAN
|
||||
assert (await b.receive_block(blocks_reorg_chain_2[21])) == ReceiveBlockResult.ADDED_TO_HEAD
|
||||
assert (await b.receive_block(blocks_reorg_chain_2[22])) == ReceiveBlockResult.ADDED_TO_HEAD
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lca(self):
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, uint64(0))
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b'0')
|
||||
store = FullNodeStore()
|
||||
await store.initialize()
|
||||
b: Blockchain = Blockchain(store, test_constants)
|
||||
|
||||
await b.initialize()
|
||||
for block in blocks:
|
||||
await b.receive_block(block)
|
||||
|
||||
assert b.lca_block == blocks[2]
|
||||
block_5_2 = bt.get_consecutive_blocks(test_constants, 1, blocks[:4], 9, uint64(1))[0]
|
||||
block_5_3 = bt.get_consecutive_blocks(test_constants, 1, blocks[:4], 9, uint64(2))[0]
|
||||
assert b.lca_block == blocks[3]
|
||||
block_5_2 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b'1')[5]
|
||||
block_5_3 = bt.get_consecutive_blocks(test_constants, 1, blocks[:5], 9, b'2')[5]
|
||||
|
||||
await b.receive_block(block_5_2)
|
||||
assert b.lca_block == blocks[3]
|
||||
assert b.lca_block == blocks[4]
|
||||
await b.receive_block(block_5_3)
|
||||
assert b.lca_block == blocks[3]
|
||||
assert b.lca_block == blocks[4]
|
||||
|
||||
reorg = bt.get_consecutive_blocks(test_constants, 6, [], 9, uint64(3))
|
||||
reorg = bt.get_consecutive_blocks(test_constants, 6, [], 9, b'3')
|
||||
for block in reorg:
|
||||
await b.receive_block(block)
|
||||
assert b.lca_block == blocks[0]
|
||||
|
|
|
@ -19,7 +19,7 @@ class TestStreamable(unittest.TestCase):
|
|||
|
||||
a = TestClass(24, 352, [1, 2, 4], [[1, 2, 3], [3, 4]], 728, None) # type: ignore
|
||||
|
||||
b: bytes = a.serialize()
|
||||
b: bytes = bytes(a)
|
||||
assert a == TestClass.from_bytes(b)
|
||||
|
||||
def test_variablesize(self):
|
||||
|
@ -32,7 +32,7 @@ class TestStreamable(unittest.TestCase):
|
|||
|
||||
a = TestClass2(uint32(1), uint32(2), "3")
|
||||
try:
|
||||
a.serialize()
|
||||
bytes(a)
|
||||
assert False
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
@ -44,7 +44,7 @@ class TestStreamable(unittest.TestCase):
|
|||
|
||||
b = TestClass3(1)
|
||||
try:
|
||||
b.serialize()
|
||||
bytes(b)
|
||||
assert False
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue