mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-08-24 10:05:29 -05:00
Squashed commit of merge conflicts.
This commit is contained in:
@@ -28,6 +28,8 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3.7-venv python3.7-distutils git -y
|
||||
sudo apt-get install nodejs-dev node-gyp libssl1.0-dev
|
||||
# Brutal work around for Github ci
|
||||
|
||||
- name: Run install script
|
||||
env:
|
||||
|
||||
@@ -117,6 +117,7 @@ class FullNodeView {
|
||||
connected_to_node_textfield.style.color = "red";
|
||||
this.state.connections = {};
|
||||
this.state.latest_blocks = [];
|
||||
this.state.latest_unfinished_blocks = [];
|
||||
create_conn_button.disabled = true;
|
||||
stop_node_button.disabled = true;
|
||||
search_button.disabled = true;
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
UpdateUrl="$(var.ARPURLUPDATEINFO)"
|
||||
UpgradeCode="$(var.bundleUpgradeCode)"
|
||||
Version="$(var.version)">
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication
|
||||
LogoFile="$(env.resourceDir)\chia_logo.png"
|
||||
LogoSideFile="$(env.resourceDir)\dialog.png"
|
||||
LicenseUrl="https://raw.githubusercontent.com/Chia-Network/chia-blockchain/master/LICENSE"
|
||||
LicenseFile="$(env.resourceDir)\eula.rtf"
|
||||
ShowFilesInUse="yes"
|
||||
ShowVersion="yes"
|
||||
SuppressOptionsUI="yes"/>
|
||||
|
||||
+1
-1
@@ -45,4 +45,4 @@ else
|
||||
echo "no venv created yet, please run install.sh"
|
||||
fi
|
||||
fi
|
||||
echo "To see how fast your timelord is likely to be try './vdf_bench squareasm 250000' for an ips estimate"
|
||||
echo "To see how fast your timelord is likely to be try './vdf_bench square_asm 250000' for an ips estimate"
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ if [ `uname` = "Linux" ]; then
|
||||
#LINUX=1
|
||||
if type apt-get; then
|
||||
# Debian/Ubuntu
|
||||
sudo apt-get install -y npm nodejs nodejs-dev node-gyp libssl1.0-dev # Brutul work around for Github ci
|
||||
sudo apt-get install -y npm nodejs
|
||||
elif type yum && [ ! -f "/etc/redhat-release" ] && [ ! -f "/etc/centos-release" ]; then
|
||||
# AMZN 2
|
||||
echo "Installing on Amazon Linux 2"
|
||||
|
||||
@@ -69,9 +69,6 @@ kwargs = dict(
|
||||
"scripts/chia-drop-db",
|
||||
"scripts/chia-restart-harvester",
|
||||
"scripts/chia-start-sim",
|
||||
"scripts/chia-start-timelord",
|
||||
"scripts/chia-start-wallet-gui",
|
||||
"scripts/chia-start-wallet-server",
|
||||
"scripts/chia-stop-all",
|
||||
],
|
||||
entry_points={
|
||||
@@ -79,7 +76,6 @@ kwargs = dict(
|
||||
"chia = src.cmds.cli:main",
|
||||
"chia-check-plots = src.cmds.check_plots:main",
|
||||
"chia-create-plots = src.cmds.create_plots:main",
|
||||
"chia-generate-keys = src.cmds.generate_keys:main",
|
||||
"chia-wallet = src.wallet.websocket_server:main",
|
||||
"chia_full_node = src.server.start_full_node:main",
|
||||
"chia_harvester = src.server.start_harvester:main",
|
||||
|
||||
+15
-4
@@ -29,6 +29,15 @@ def make_parser(parser):
|
||||
default=True,
|
||||
help="Regenerate pool keys",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--pooltarget",
|
||||
type=str2bool,
|
||||
nargs="?",
|
||||
const=True,
|
||||
default=True,
|
||||
help="Regenerate pool target",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-w",
|
||||
"--wallet",
|
||||
@@ -39,10 +48,7 @@ def make_parser(parser):
|
||||
help="Regenerate wallet keys",
|
||||
)
|
||||
parser.add_argument(
|
||||
"keys",
|
||||
help='must the literal "keys"',
|
||||
type=str,
|
||||
nargs=1,
|
||||
"keys", help='must the literal "keys"', type=str, nargs=1,
|
||||
)
|
||||
parser.set_defaults(function=generate)
|
||||
|
||||
@@ -99,3 +105,8 @@ def generate(args, parser):
|
||||
key_config["pool_sks"] = [bytes(pool_sk).hex() for pool_sk in pool_sks]
|
||||
key_config["pool_target"] = pool_target.hex()
|
||||
save_config(root_path, keys_yaml, key_config)
|
||||
if args.pooltarget:
|
||||
# Compute a new pool target and save it to the config
|
||||
assert "wallet_target" in key_config
|
||||
key_config["pool_target"] = key_config["wallet_target"]
|
||||
save_config(root_path, keys_yaml, key_config)
|
||||
|
||||
+1
-1
@@ -139,6 +139,6 @@ def chia_init(args):
|
||||
else:
|
||||
create_default_chia_config(root_path)
|
||||
initialize_ssl(root_path)
|
||||
print("Please generate your keys with chia-generate-keys")
|
||||
print("Please generate your keys with chia generate keys")
|
||||
|
||||
return 0
|
||||
|
||||
+10
-97
@@ -50,83 +50,6 @@ def human_local_time(timestamp):
|
||||
return time.strftime("%a %b %d %Y %T %Z", time_local)
|
||||
|
||||
|
||||
async def compare_block_headers(client, oldblock_hash, newblock_hash):
|
||||
block_older_header = await client.get_header(hexstr_to_bytes(oldblock_hash))
|
||||
block_newer_header = await client.get_header(hexstr_to_bytes(newblock_hash))
|
||||
if block_older_header is not None:
|
||||
block_older_time_string = human_local_time(
|
||||
block_older_header.data.timestamp
|
||||
)
|
||||
block_newer_time_string = human_local_time(
|
||||
block_newer_header.data.timestamp
|
||||
)
|
||||
elapsed_time_seconds = (
|
||||
block_newer_header.data.timestamp
|
||||
- block_older_header.data.timestamp
|
||||
)
|
||||
time_delta = datetime.timedelta(seconds=elapsed_time_seconds)
|
||||
print("Older Block", block_older_header.data.height, ":")
|
||||
print(
|
||||
f"Header Hash 0x{oldblock_hash}\n"
|
||||
f"Timestamp {block_older_time_string}\n"
|
||||
f"Weight {block_older_header.data.weight}\n"
|
||||
f"Total VDF Iterations {block_older_header.data.total_iters}\n"
|
||||
)
|
||||
print("Newer Block", block_newer_header.data.height, ":")
|
||||
print(
|
||||
f"Header Hash 0x{newblock_hash}\n"
|
||||
f"Timestamp {block_newer_time_string}\n"
|
||||
f"Weight {block_newer_header.data.weight}\n"
|
||||
f"Total VDF Iterations {block_newer_header.data.total_iters}\n"
|
||||
)
|
||||
delta_weight = (
|
||||
block_newer_header.data.weight - block_older_header.data.weight
|
||||
)
|
||||
delta_iters = (
|
||||
block_newer_header.data.total_iters
|
||||
- block_older_header.data.total_iters
|
||||
)
|
||||
|
||||
block_older = await client.get_block(hexstr_to_bytes(oldblock_hash))
|
||||
block_newer = await client.get_block(hexstr_to_bytes(newblock_hash))
|
||||
delta_iters -= await get_total_miniters(
|
||||
client, block_older, block_newer
|
||||
)
|
||||
weight_div_iters = delta_weight / delta_iters
|
||||
tips_adjustment_constant = 0.65
|
||||
network_space_constant = 2 ** 32 # 2^32
|
||||
network_space_bytes_estimate = (
|
||||
weight_div_iters * network_space_constant * tips_adjustment_constant
|
||||
)
|
||||
network_space_terrabytes_estimate = (
|
||||
network_space_bytes_estimate / 1024**4
|
||||
)
|
||||
print(
|
||||
f"The elapsed time between blocks is reported as {time_delta}.\n"
|
||||
f"The network has an estimated {network_space_terrabytes_estimate:.2f}TB"
|
||||
)
|
||||
else:
|
||||
print("Block with header hash", oldblock_hash, "not found.")
|
||||
|
||||
async def get_total_miniters(rpc_client, old_block, new_block):
|
||||
"""
|
||||
Calculates the sum of min_iters from all blocks starting from old and up to and including
|
||||
new_block.
|
||||
# TODO: compute real min_iters for multiple epochs, using height RPC
|
||||
"""
|
||||
old_block_parent = await rpc_client.get_header(old_block.prev_header_hash)
|
||||
new_block_parent = await rpc_client.get_header(new_block.prev_header_hash)
|
||||
old_diff = old_block.weight - old_block_parent.weight
|
||||
new_diff = new_block.weight - new_block_parent.weight
|
||||
mi1 = calculate_min_iters_from_iterations(
|
||||
old_block.proof_of_space, old_diff, old_block.proof_of_time.number_of_iterations
|
||||
)
|
||||
mi2 = calculate_min_iters_from_iterations(
|
||||
new_block.proof_of_space, new_diff, new_block.proof_of_time.number_of_iterations
|
||||
)
|
||||
return (new_block.height - old_block.height) * ((mi2 + mi1) / 2)
|
||||
|
||||
|
||||
async def get_total_miniters(rpc_client, old_block, new_block):
|
||||
"""
|
||||
Calculates the sum of min_iters from all blocks starting from old and up to and including
|
||||
@@ -164,15 +87,10 @@ async def compare_block_headers(client, oldblock_hash, newblock_hash):
|
||||
block_older_header = await client.get_header(hexstr_to_bytes(oldblock_hash))
|
||||
block_newer_header = await client.get_header(hexstr_to_bytes(newblock_hash))
|
||||
if block_older_header is not None:
|
||||
block_older_time_string = human_local_time(
|
||||
block_older_header.data.timestamp
|
||||
)
|
||||
block_newer_time_string = human_local_time(
|
||||
block_newer_header.data.timestamp
|
||||
)
|
||||
block_older_time_string = human_local_time(block_older_header.data.timestamp)
|
||||
block_newer_time_string = human_local_time(block_newer_header.data.timestamp)
|
||||
elapsed_time_seconds = (
|
||||
block_newer_header.data.timestamp
|
||||
- block_older_header.data.timestamp
|
||||
block_newer_header.data.timestamp - block_older_header.data.timestamp
|
||||
)
|
||||
time_delta = datetime.timedelta(seconds=elapsed_time_seconds)
|
||||
print("Older Block", block_older_header.data.height, ":")
|
||||
@@ -189,28 +107,21 @@ async def compare_block_headers(client, oldblock_hash, newblock_hash):
|
||||
f"Weight {block_newer_header.data.weight}\n"
|
||||
f"Total VDF Iterations {block_newer_header.data.total_iters}\n"
|
||||
)
|
||||
delta_weight = (
|
||||
block_newer_header.data.weight - block_older_header.data.weight
|
||||
)
|
||||
delta_weight = block_newer_header.data.weight - block_older_header.data.weight
|
||||
delta_iters = (
|
||||
block_newer_header.data.total_iters
|
||||
- block_older_header.data.total_iters
|
||||
block_newer_header.data.total_iters - block_older_header.data.total_iters
|
||||
)
|
||||
|
||||
block_older = await client.get_block(hexstr_to_bytes(oldblock_hash))
|
||||
block_newer = await client.get_block(hexstr_to_bytes(newblock_hash))
|
||||
delta_iters -= await get_total_miniters(
|
||||
client, block_older, block_newer
|
||||
)
|
||||
delta_iters -= await get_total_miniters(client, block_older, block_newer)
|
||||
weight_div_iters = delta_weight / delta_iters
|
||||
tips_adjustment_constant = 0.65
|
||||
network_space_constant = 2 ** 32 # 2^32
|
||||
network_space_bytes_estimate = (
|
||||
weight_div_iters * network_space_constant * tips_adjustment_constant
|
||||
)
|
||||
network_space_terrabytes_estimate = (
|
||||
network_space_bytes_estimate / 1024**4
|
||||
)
|
||||
network_space_terrabytes_estimate = network_space_bytes_estimate / 1024 ** 4
|
||||
print(
|
||||
f"The elapsed time between blocks is reported as {time_delta}.\n"
|
||||
f"The network has an estimated {network_space_terrabytes_estimate:.2f}TB"
|
||||
@@ -237,7 +148,9 @@ async def netstorge_async(args, parser):
|
||||
lca_block_hash = str(blockchain_state["lca"].header_hash)
|
||||
lca_block_height = blockchain_state["lca"].data.height
|
||||
older_block_height = lca_block_height - int(args.delta_block_height)
|
||||
print(f"LCA Block Height is {lca_block_height} - Comparing to {older_block_height}\n")
|
||||
print(
|
||||
f"LCA Block Height is {lca_block_height} - Comparing to {older_block_height}\n"
|
||||
)
|
||||
older_block_header = await client.get_header_by_height(older_block_height)
|
||||
older_block_header_hash = str(older_block_header.get_hash())
|
||||
await compare_block_headers(client, older_block_header_hash, lca_block_hash)
|
||||
|
||||
+11
-11
@@ -231,7 +231,6 @@ async def show_async(args, parser):
|
||||
block_header = await client.get_block(
|
||||
hexstr_to_bytes(args.block_header_hash)
|
||||
)
|
||||
# print(dir(block_header))
|
||||
if block_header is not None:
|
||||
print("Block header:")
|
||||
print(block_header.header)
|
||||
@@ -253,16 +252,17 @@ async def show_async(args, parser):
|
||||
aggregated_signature = block.header.data.aggregated_signature.sig
|
||||
print("Block", block.header.data.height, ":")
|
||||
print(
|
||||
f"Header Hash 0x{args.block_by_header_hash}\n"
|
||||
f"Timestamp {block_time_string}\n"
|
||||
f"Height {block.header.data.height}\n"
|
||||
f"Weight {block.header.data.weight}\n"
|
||||
f"Previous Block 0x{block.header.data.prev_header_hash}\n"
|
||||
f"Cost {block.header.data.cost}\n"
|
||||
f"Difficulty {block.header.data.weight-prev_block_header.header.data.weight}\n"
|
||||
f"Total VDF Iterations {block.header.data.total_iters}\n"
|
||||
f"Block VDF Iterations {block.proof_of_time.number_of_iterations}\n"
|
||||
f"Proof of Space 'k' Size {block.proof_of_space.size}\n"
|
||||
f"Header Hash 0x{args.block_by_header_hash}\n"
|
||||
f"Timestamp {block_time_string}\n"
|
||||
f"Height {block.header.data.height}\n"
|
||||
f"Weight {block.header.data.weight}\n"
|
||||
f"Previous Block 0x{block.header.data.prev_header_hash}\n"
|
||||
f"Cost {block.header.data.cost}\n"
|
||||
f"Difficulty {block.header.data.weight-prev_block_header.header.data.weight}\n"
|
||||
f"Total VDF Iterations {block.header.data.total_iters}\n"
|
||||
f"Block VDF Iterations {block.proof_of_time.number_of_iterations}\n"
|
||||
f"PoTime Witness Type {block.proof_of_time.witness_type}\n"
|
||||
f"PoSpace 'k' Size {block.proof_of_space.size}\n"
|
||||
# f"Plot Public Key 0x{block.proof_of_space.plot_pubkey}\n"
|
||||
# f"Pool Public Key 0x{block.proof_of_space.pool_pubkey}\n"
|
||||
f"Tx Filter Hash {b'block.transactions_filter'.hex()}\n"
|
||||
|
||||
+4
-6
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import subprocess
|
||||
from typing import List
|
||||
|
||||
|
||||
SCRIPTS_FOR_SERVICE = {
|
||||
@@ -18,10 +19,7 @@ SCRIPTS_FOR_SERVICE["wallet-server"] = SCRIPTS_FOR_SERVICE["wallet"][1:]
|
||||
def make_parser(parser):
|
||||
|
||||
parser.add_argument(
|
||||
"service",
|
||||
choices=SCRIPTS_FOR_SERVICE.keys(),
|
||||
type=str,
|
||||
nargs="+",
|
||||
"service", choices=SCRIPTS_FOR_SERVICE.keys(), type=str, nargs="+",
|
||||
)
|
||||
parser.set_defaults(function=start)
|
||||
|
||||
@@ -31,7 +29,7 @@ def start(args, parser):
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
processes = []
|
||||
processes: List = []
|
||||
for service in args.service:
|
||||
processes.extend(start_service(args.root_path, service))
|
||||
|
||||
@@ -57,7 +55,7 @@ def start_service(root_path, service):
|
||||
# and we need to pass on the possibly altered CHIA_ROOT
|
||||
os.environ["CHIA_ROOT"] = str(root_path)
|
||||
|
||||
for script in SCRIPTS_FOR_SERVICE.get(service):
|
||||
for script in SCRIPTS_FOR_SERVICE[service]:
|
||||
process = subprocess.Popen(script.split())
|
||||
processes.append(process)
|
||||
return processes
|
||||
|
||||
@@ -6,6 +6,8 @@ def calculate_block_reward(height: uint32) -> uint64:
|
||||
Returns the coinbase reward at a certain block height.
|
||||
1 Chia coin = 16,000,000,000,000 = 16 trillion mojo.
|
||||
"""
|
||||
if height == 0:
|
||||
return uint64(500000000000000000)
|
||||
return uint64(14000000000000)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ from typing import Any, Dict
|
||||
|
||||
constants: Dict[str, Any] = {
|
||||
"NUMBER_OF_HEADS": 3, # The number of tips each full node keeps track of and propagates
|
||||
"DIFFICULTY_STARTING": 500, # These are in units of 2^32
|
||||
# DIFFICULTY_STARTING is the starting difficulty for the first epoch, which is then further
|
||||
# multiplied by another factor of 2^32, to be used in the VDF iter calculation formula.
|
||||
"DIFFICULTY_STARTING": 2 ** 32,
|
||||
"DIFFICULTY_FACTOR": 3, # The next difficulty is truncated to range [prev / FACTOR, prev * FACTOR]
|
||||
# These 3 constants must be changed at the same time
|
||||
"DIFFICULTY_EPOCH": 128, # The number of blocks per epoch
|
||||
@@ -16,7 +18,7 @@ constants: Dict[str, Any] = {
|
||||
# will be contant and required for all blocks.
|
||||
"MIN_ITERS_PROPORTION": 10,
|
||||
# For the first epoch, since we have no previous blocks, we can't estimate vdf iterations per second
|
||||
"MIN_ITERS_STARTING": (2 ** 17),
|
||||
"MIN_ITERS_STARTING": (2 ** 22),
|
||||
"MAX_FUTURE_TIME": 7200, # The next block can have a timestamp of at most these many seconds more
|
||||
"NUMBER_OF_TIMESTAMPS": 11, # Than the average of the last NUMBEBR_OF_TIMESTAMPS blocks
|
||||
# If an unfinished block is more than these many seconds slower than the best unfinished block,
|
||||
@@ -27,7 +29,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^\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
|
||||
"GENESIS_BLOCK": b"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x00[\x8c6\x15\x85\xbfg\x1c{\x19\xe5\x91y\x90,\rd\x0b=\x0b\x84\x8f\x9c\x83#k&&\xf3\xff\xd8\xb5\x009\x98\xd7\xaa\xe7\xbc\xde\xe2B\xd1\xe8\xd6\xdb\xa1\x10\xd4\x95\x81\xdf\xac\x1a\x00\xa5\x92j1\tN\xc0)\xb1\xa8\xc0\\\xb4J0!\x0f\x030\xc0\xb9\xdb\xebb\rt{\x90\xb8V&\x97\xf5\x95\x1d\"\xc83&\xb1\x1f\x00\x00\x00\xf8\x81\xa6\x0by['@\x9d\x8f\xf2\xc52\xe4\xe04^%}\x91\x83\x8e\xf6\x8b\xfd\xec~e\xac\x84;u\xf7IW\xb0\x1b\x1e\xc5\xc5z)\x9d\xb8Ci\x84\x0f0\x18gl\x1eK5\xd4\x82\xfd[q\x18P/\x17[\xb1\x9c\xbc\x91\x90\x17{A~C\xe0{F\xaf\xef\x14\xd7\xd3\xc8M\x04s\x14\xab\xc5\x91Not'\x1a\xb9\x8cs\x8a\x0f\xda\x8b\xf9\xda\xe4\xf2\xf8\x98\xbe\xad\xb4\x1f\xea\xae/\xb4$!l\xb3\xd43%\xc3~B\x18\x12m\xa0\x801\x0c\xf67Gr\x85S o>\xcb\x17I\x94\x1a\xe4,k\x06\x7f\xe4/<\xbcQJ\x97e\x8d\xd3Y[\x0c=\x1d\xe7\xde\x11\xac\xaac\xc4kT\xac\xe6\xeeZ\x0b@?\x81\x95\xa6\xb2\x08R\x8cb\xcb)\"\xb9\xe9\xd8\x05!2,\xd6\xa1\xf1\x08}\xc8$0\xda\xf7\x11o\xf6\x13<\x9e\x17\xe2\xe9\xb5b\xa6/\xd6\xf6\xaa\x9e\xbd\xb4\x1e\xdc\x85\xf0\x13}\xf6\x93\xc3\x07\x806xM\xd1u\xa8\xd3\x01\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x00\x00\x00\x00\x00QT\x0c\x00!.\x97k\xa5\xb3tPU\xa6\xa7^\x91^u\xdc\x9d\rq\x18\xa1,\x16Q\xf3\xe3\xe5\xdd\xd2L\xb7\xa2\xeaO8\xfa\x80[8\\\x90\r&\xa5\xa6\xb9\x8f?\xa8@}\x06+,\xf0|\xd0\xca\"\xe8\xa6UX\xa3\x00\x11\x86\xe7J\x9a5\x10;\xcb\xd4{\xde_\x1eX\x1ax\xd6\xd6\xa1$>\x184\x01z\x12\x9b\xc7>\x1bS\xff\xe7\x95\x8d\xed\xe4|\x1a\xed\xab\xbe<\xeb5\xf4\xcb4a\xdd\xbe\xecb\xc9\xf0\xa6e\x8b\x16j=\xfa1\x00\x00\x00\x00\x82\x00\x10\x1b\x8d3p\x15L\x9a\xbd\nc0\tZ\xc5p\xcdpVwt\xd6\x8f\x8a-\xeb4\x9b#\x07\x96\xa5\xe2\xcf\x9e\xf6\x92M\xe0C\xc2\xef\x8bR\xcc\xf9:\xd4&t\xefC\xc1\xc2\xa1\xe7V\xcd(\x9ff\xe3\xb9\x86\xff\xf3gY\x0c`\xa9\xba\xd3]YV\x01\xd0\xb7H%\xdd\xc8t\xcd1\xae\x9d\x1f\xb4\xca\x9f\x90\xf6r\t\xf4x@\xd6I3*H\xe1c\x9eeEU\xb4\x04\xba\xd8\nj\x93\xa9\xf0\xc0\xef>o\x05h\x16\x89\xd2\x85\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^\x9e\xc7\xa2\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\x06\x81\x15e\xbf\xf7\xe9\nx\xc4\x85\xa2\xec\xa9\xc8\xde\x967\xc4\xb4\xd5\x82\x89n\x92\x9b \xb8g\x07\xf8i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00QT\x0c\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\xa4%\x91\x82\xb4\xd8\xe0\xaf!3\x1f\xc5\xbe&\x81\xf9S@\x0bg&\xfa@\x95\xe3\xb9\x1a\xe8\xf0\x05\xa86\x06\xf0[Y\xd3\xb2\x00\x00\xcc\xe7\xc9T1\xfb\x0c\xf5_\xf0\xb0r5\x8c\xa3\xb9\x86D\x89\x1e\xf0\x8b\x08\xd9\x19\x93\xc6\xcf\xc7\xaf\xea~\xda\xa5l\xf9\xac\xe2\xb0\x99\x9a\x91q\xe4\\\x8eu\xdc\n\xc2i\xe3\x93\x85\xabf{\x08yC\xe7e-r\x936\x0f\x16~)\xef\xb2\x9d\xd7\x9b\x1f\x97Q\xa3\xd6&\xf3E\xc9CF1l\xb6\x0b;t\x1f\xed\x8e\xc4\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\xa4%\x91\x82\xb4\xd8\xe0\xaf!3\x1f\xc5\xbe&\x81\xf9S@\x0bg&\xfa@\x95\xe3\xb9\x1a\xe8\xf0\x05\xa86\x00\x00\x01\xd1\xa9J \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe3\x1e4\xb7N\x81\xe2\x1fj\x8ff\xda\xdcq\xd4U\x9f\x0bPY\xea\xa1g\xa3\xed\x9f\xc6\xe3\xcc\xb34[\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@\xafn\x13D\xb8t\x9d\x04\xc60z\xfe\x89\x8f\xb4\xa3K\xde}\x0b\xf2G\xb1_\x8c\xca\xa6\xf0~\xfe\xa2\x0b\xde\xdb2\x1a\xe9\x8e2RU\x8f\xbbd\xab\x9f\xf2\x19\xc4L\xd3:\xbe\xe94\xcf\x08'\x17)V4u-\x15VE\xe7\xfd!\xa6(\x0fY]'\xb2\x834\xbds\xaa% &c\xbd\\\xeb9\x9e\x92\xfef:\x00\x00", # noqa: E501
|
||||
# Target tx count per sec
|
||||
"TX_PER_SEC": 20,
|
||||
# Size of mempool = 10x the size of block
|
||||
|
||||
+1
-1
@@ -339,7 +339,7 @@ class Farmer:
|
||||
]
|
||||
|
||||
coinbase_reward = uint64(
|
||||
calculate_block_reward(proof_of_space_finalized.height)
|
||||
calculate_block_reward(uint32(proof_of_space_finalized.height + 1))
|
||||
)
|
||||
|
||||
coinbase_coin, coinbase_signature = create_coinbase_coin_and_signature(
|
||||
|
||||
@@ -110,14 +110,28 @@ class Blockchain:
|
||||
else:
|
||||
raise RuntimeError(f"Invalid genesis block {self.genesis}")
|
||||
|
||||
headers_input: Dict[str, Header] = await self._load_headers_from_store()
|
||||
start = time.time()
|
||||
headers_input, lca_hash = await self._load_headers_from_store()
|
||||
log.info(f"Read from disk in {time.time() - start}")
|
||||
start = time.time()
|
||||
|
||||
assert self.lca_block is not None
|
||||
if len(headers_input) > 0:
|
||||
self.headers = headers_input
|
||||
for _, header in self.headers.items():
|
||||
self.height_to_hash[header.height] = header.header_hash
|
||||
await self._reconsider_heads(header, False)
|
||||
sorted_headers = sorted(self.headers.items(), key=lambda b: b[1].height)
|
||||
if lca_hash is not None:
|
||||
# Add all blocks up to the LCA, and set the tip to the LCA
|
||||
assert sorted_headers[-1][0] == lca_hash
|
||||
for _, header in sorted_headers:
|
||||
self.height_to_hash[header.height] = header.header_hash
|
||||
self.tips = [header]
|
||||
self.lca_block = header
|
||||
await self._reconsider_heads(self.lca_block, False)
|
||||
else:
|
||||
for _, header in sorted_headers:
|
||||
# Reconsider every single header, since we don't have LCA on disk
|
||||
self.height_to_hash[header.height] = header.header_hash
|
||||
await self._reconsider_heads(header, False)
|
||||
assert (
|
||||
self.headers[self.height_to_hash[uint32(0)]].get_hash()
|
||||
== self.genesis.header_hash
|
||||
@@ -127,18 +141,26 @@ class Blockchain:
|
||||
self.headers[self.height_to_hash[uint32(1)]].prev_header_hash
|
||||
== self.genesis.header_hash
|
||||
)
|
||||
log.info(f"Added to chain in {time.time() - start}")
|
||||
return self
|
||||
|
||||
async def _load_headers_from_store(self) -> Dict[str, Header]:
|
||||
async def _load_headers_from_store(
|
||||
self,
|
||||
) -> Tuple[Dict[str, Header], Optional[bytes32]]:
|
||||
"""
|
||||
Loads headers from disk, into a list of Headers, that can be used
|
||||
to initialize the Blockchain class.
|
||||
"""
|
||||
lca_hash: Optional[bytes32] = await self.store.get_lca()
|
||||
seen_blocks: Dict[str, Header] = {}
|
||||
tips: List[Header] = []
|
||||
for header in await self.store.get_headers():
|
||||
if not tips or header.weight > tips[0].weight:
|
||||
tips = [header]
|
||||
if lca_hash is not None:
|
||||
if header.header_hash == lca_hash:
|
||||
tips = [header]
|
||||
else:
|
||||
if len(tips) == 0 or header.weight > tips[0].weight:
|
||||
tips = [header]
|
||||
seen_blocks[header.header_hash] = header
|
||||
|
||||
headers = {}
|
||||
@@ -151,7 +173,7 @@ class Blockchain:
|
||||
|
||||
for block in reversed(reverse_blocks):
|
||||
headers[block.header_hash] = block
|
||||
return headers
|
||||
return headers, lca_hash
|
||||
|
||||
def get_current_tips(self) -> List[Header]:
|
||||
"""
|
||||
@@ -877,6 +899,8 @@ class Blockchain:
|
||||
assert full is not None
|
||||
await self.unspent_store.new_lca(full)
|
||||
await self._create_diffs_for_tips(self.lca_block)
|
||||
if not genesis:
|
||||
await self.store.set_lca(self.lca_block.header_hash)
|
||||
# If LCA changed update the unspent store
|
||||
elif old_lca.header_hash != self.lca_block.header_hash:
|
||||
# New LCA is lower height but not the a parent of old LCA (Reorg)
|
||||
@@ -890,6 +914,8 @@ class Blockchain:
|
||||
await self._from_fork_to_lca(fork_head, self.lca_block)
|
||||
if not self.store.get_sync_mode():
|
||||
await self.recreate_diff_stores()
|
||||
if not genesis:
|
||||
await self.store.set_lca(self.lca_block.header_hash)
|
||||
else:
|
||||
# If LCA has not changed just update the difference
|
||||
self.unspent_store.nuke_diffs()
|
||||
|
||||
@@ -253,6 +253,7 @@ class FullNode:
|
||||
self.log.info("Waiting to receive tips from peers.")
|
||||
self.store.set_waiting_for_tips(True)
|
||||
# TODO: better way to tell that we have finished receiving tips
|
||||
# TODO: fix DOS issue. Attacker can request syncing to an invalid blockchain
|
||||
await asyncio.sleep(5)
|
||||
highest_weight: uint128 = uint128(0)
|
||||
tip_block: FullBlock
|
||||
|
||||
@@ -77,6 +77,11 @@ class FullNodeStore:
|
||||
"text PRIMARY KEY, proof_hash text, header blob)"
|
||||
)
|
||||
|
||||
# LCA
|
||||
await self.db.execute(
|
||||
"CREATE TABLE IF NOT EXISTS lca(header_hash text PRIMARY KEY)"
|
||||
)
|
||||
|
||||
# Height index so we can look up in order of height for sync purposes
|
||||
await self.db.execute(
|
||||
"CREATE INDEX IF NOT EXISTS block_height on blocks(height)"
|
||||
@@ -116,6 +121,22 @@ class FullNodeStore:
|
||||
await self.db.execute("DELETE FROM headers")
|
||||
await self.db.commit()
|
||||
|
||||
async def get_lca(self) -> Optional[bytes32]:
|
||||
cursor = await self.db.execute("SELECT * from lca")
|
||||
row = await cursor.fetchone()
|
||||
await cursor.close()
|
||||
if row is not None:
|
||||
return bytes32(bytes.fromhex(row[0]))
|
||||
return None
|
||||
|
||||
async def set_lca(self, header_hash: bytes32) -> None:
|
||||
await self.db.execute("DELETE FROM lca")
|
||||
cursor_1 = await self.db.execute(
|
||||
"INSERT OR REPLACE INTO lca VALUES(?)", (header_hash.hex(),)
|
||||
)
|
||||
await cursor_1.close()
|
||||
await self.db.commit()
|
||||
|
||||
async def add_block(self, block: FullBlock) -> None:
|
||||
assert block.proof_of_time is not None
|
||||
cursor_1 = await self.db.execute(
|
||||
|
||||
+44
-36
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Tuple
|
||||
from typing import Dict, Optional, Tuple, List
|
||||
|
||||
from blspy import PrependSignature, PrivateKey, PublicKey, Util
|
||||
|
||||
@@ -19,6 +19,46 @@ from src.util.path import path_from_root
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_plots(
|
||||
config_file: Dict, plot_config_file: Dict, pool_pubkeys: List[PublicKey]
|
||||
) -> Dict[Path, DiskProver]:
|
||||
provers: Dict[Path, DiskProver] = {}
|
||||
for partial_filename_str, plot_config in plot_config_file["plots"].items():
|
||||
plot_root = path_from_root(DEFAULT_ROOT_PATH, config_file.get("plot_root", "."))
|
||||
partial_filename = plot_root / partial_filename_str
|
||||
potential_filenames = [
|
||||
partial_filename,
|
||||
path_from_root(plot_root, partial_filename_str),
|
||||
]
|
||||
pool_pubkey = PublicKey.from_bytes(bytes.fromhex(plot_config["pool_pk"]))
|
||||
|
||||
# Only use plots that correct pools associated with them
|
||||
if pool_pubkey not in pool_pubkeys:
|
||||
log.warning(
|
||||
f"Plot {partial_filename} has a pool key that is not in the farmer's pool_pk list."
|
||||
)
|
||||
continue
|
||||
|
||||
found = False
|
||||
failed_to_open = False
|
||||
for filename in potential_filenames:
|
||||
if filename.exists():
|
||||
try:
|
||||
provers[partial_filename_str] = DiskProver(str(filename))
|
||||
except ValueError:
|
||||
log.error(f"Failed to open file {filename}.")
|
||||
failed_to_open = True
|
||||
break
|
||||
log.info(
|
||||
f"Farming plot {filename} of size {provers[partial_filename_str].get_size()}"
|
||||
)
|
||||
found = True
|
||||
break
|
||||
if not found and not failed_to_open:
|
||||
log.warning(f"Plot at {potential_filenames} does not exist.")
|
||||
return provers
|
||||
|
||||
|
||||
class Harvester:
|
||||
def __init__(self, config: Dict, plot_config: Dict):
|
||||
self.config: Dict = config
|
||||
@@ -97,41 +137,9 @@ class Harvester:
|
||||
which must be put into the plots, before the plotting process begins. We cannot
|
||||
use any plots which don't have one of the pool keys.
|
||||
"""
|
||||
for partial_filename_str, plot_config in self.plot_config["plots"].items():
|
||||
plot_root = path_from_root(
|
||||
DEFAULT_ROOT_PATH, self.config.get("plot_root", ".")
|
||||
)
|
||||
partial_filename = plot_root / partial_filename_str
|
||||
potential_filenames = [
|
||||
partial_filename,
|
||||
path_from_root(plot_root, partial_filename_str),
|
||||
]
|
||||
pool_pubkey = PublicKey.from_bytes(bytes.fromhex(plot_config["pool_pk"]))
|
||||
|
||||
# Only use plots that correct pools associated with them
|
||||
if pool_pubkey not in harvester_handshake.pool_pubkeys:
|
||||
log.warning(
|
||||
f"Plot {partial_filename} has a pool key that is not in the farmer's pool_pk list."
|
||||
)
|
||||
continue
|
||||
|
||||
found = False
|
||||
failed_to_open = False
|
||||
for filename in potential_filenames:
|
||||
if filename.exists():
|
||||
try:
|
||||
self.provers[partial_filename_str] = DiskProver(str(filename))
|
||||
except ValueError:
|
||||
log.error(f"Failed to open file {filename}.")
|
||||
failed_to_open = True
|
||||
break
|
||||
log.info(
|
||||
f"Farming plot {filename} of size {self.provers[partial_filename_str].get_size()}"
|
||||
)
|
||||
found = True
|
||||
break
|
||||
if not found and not failed_to_open:
|
||||
log.warning(f"Plot at {potential_filenames} does not exist.")
|
||||
self.provers = load_plots(
|
||||
self.config, self.plot_config, harvester_handshake.pool_pubkeys
|
||||
)
|
||||
if len(self.provers) == 0:
|
||||
log.warning(
|
||||
"Not farming any plots on this harvester. Check your configuration."
|
||||
|
||||
@@ -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.12"
|
||||
protocol_version = "0.0.13"
|
||||
|
||||
"""
|
||||
Handshake when establishing a connection between two servers.
|
||||
|
||||
@@ -103,13 +103,12 @@ class RpcApiHandler:
|
||||
if "height" not in request_data:
|
||||
raise web.HTTPBadRequest()
|
||||
header_height = uint32(int(request_data["height"]))
|
||||
header_hash_string: Optional[bytes32] = self.full_node.blockchain.height_to_hash[header_height]
|
||||
header_hash = hexstr_to_bytes(str(header_hash_string))
|
||||
header: Optional[Header] = self.full_node.blockchain.headers.get(
|
||||
header_hash, None
|
||||
header_hash: Optional[bytes32] = self.full_node.blockchain.height_to_hash.get(
|
||||
header_height, None
|
||||
)
|
||||
if header is None:
|
||||
if header_hash is None:
|
||||
raise web.HTTPNotFound()
|
||||
header: Header = self.full_node.blockchain.headers[header_hash]
|
||||
return obj_to_response(header)
|
||||
|
||||
async def get_header(self, request) -> web.Response:
|
||||
|
||||
@@ -81,9 +81,6 @@ class ChiaServer:
|
||||
self.root_path = root_path
|
||||
self.config = config
|
||||
|
||||
def loadSSLConfig(self, tipo: str, path: Path, config: Dict):
|
||||
if config is not None:
|
||||
|
||||
def loadSSLConfig(self, tipo: str, path: Path, config: Dict):
|
||||
if config is not None:
|
||||
try:
|
||||
|
||||
@@ -16,7 +16,7 @@ test_constants: Dict[str, Any] = {
|
||||
"DIFFICULTY_DELAY": 3, # EPOCH / WARP_FACTOR
|
||||
"MIN_ITERS_STARTING": 50 * 2,
|
||||
"COINBASE_FREEZE_PERIOD": 0,
|
||||
"GENESIS_BLOCK": b'\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\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\x17\xd2\xcc\xd7\xb4m\x94\xb7V\x959\xed4\x89\x04b\x08\x07^\xca`\x8f#%\xe9\x9c\x9d\x86y\x10\x96W\x9d\xce\xc1\x15r\x97\x91U\n\x11<\xdf\xb2\xfc\xfb<\x13\x00\x00\x00\x98\xf4\x88\xcb\xb2MYo]\xaf \xd8a>\x06\xfe\xc8F\x8d\x15\x90\x15\xbb\x04\xd48\x10\xc6\xd8b\x82\x88\x7fx<\xe5\xe6\x8b\x8f\x84\xdd\x1cU"\x83\xfb7\x9d`\xb0I\xb3\xbe;bvE\xc6\x92\xdd\xbe\x988\xe9y;\xc6.\xa1\xce\x94\xdc\xd8\xab\xaf\xba\x8f\xd8r\x8br\xc8\xa0\xac\xc0\xe9T\x87\x08\x08\x8b#-\xb6o\xf0\x1f\x0bzv\xb3\x81\x1a\xd4\xf7\x01\xdf\xc5A\x11\xe0\x0c\xc0\x87\xa6\xc2v\xbbR\xc4{"\xa5\xe5\xe0bx7\xfa\n\xae\xea\xfe\x02\xac\xef\xec\xd1\xc2\xc55\x06{\xe1\x0c\xb2\x99q\xd7\xd8\xcb\x97\x86\x01\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\x08\xde\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\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\x04\x00#\xff\xf7\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^\x8e\x8bO\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}\xe7@\xfc\xa6\xaf\xc6\xec\xe8\xba\x19\xa3\x9b\x19vq\x91C\xa2\xe3\xde\x1f\xf1zB.\xf2\xc2\xc3,\x06\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x08\xde\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\x00p\xc7\xd4\x8a3\x98\x00)\r0\xb7\x83!Z\xf9\x99\x95\xaeS\x1cI\xa9G\xa9\x85,\xb6z\xe7\x05\xcb\xaa\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\xd4\xa6\xe0&\x88h6aWn\xeaf"\x9e\xca\xb9\xebu\xe9\xbf\xee\xc5ui\xf2\x0b\xab\x85 \xbb\x04\xb3y\xa9R\xcb>Q\x89B\xe2d\x8c\x01\xe2i_J\x0e\xbf8\xb3\x90\x94\x95@U\xd7\xf6A~\xfe\x91$M\xca\xfd\x07\xdb\x1fb\xca\x06\x08\xdd(?\x87\x92\xf8\x082\x9c\x87\xfcL\xb4\xe2\x9a-OstY\xe9m\x00\x00' # noqa: E501
|
||||
"GENESIS_BLOCK": b'\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\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\x17\xd2\xcc\xd7\xb4m\x94\xb7V\x959\xed4\x89\x04b\x08\x07^\xca`\x8f#%\xe9\x9c\x9d\x86y\x10\x96W\x9d\xce\xc1\x15r\x97\x91U\n\x11<\xdf\xb2\xfc\xfb<\x13\x00\x00\x00\x98\xf4\x88\xcb\xb2MYo]\xaf \xd8a>\x06\xfe\xc8F\x8d\x15\x90\x15\xbb\x04\xd48\x10\xc6\xd8b\x82\x88\x7fx<\xe5\xe6\x8b\x8f\x84\xdd\x1cU"\x83\xfb7\x9d`\xb0I\xb3\xbe;bvE\xc6\x92\xdd\xbe\x988\xe9y;\xc6.\xa1\xce\x94\xdc\xd8\xab\xaf\xba\x8f\xd8r\x8br\xc8\xa0\xac\xc0\xe9T\x87\x08\x08\x8b#-\xb6o\xf0\x1f\x0bzv\xb3\x81\x1a\xd4\xf7\x01\xdf\xc5A\x11\xe0\x0c\xc0\x87\xa6\xc2v\xbbR\xc4{"\xa5\xe5\xe0bx7\xfa\n\xae\xea\xfe\x02\xac\xef\xec\xd1\xc2\xc55\x06{\xe1\x0c\xb2\x99q\xd7\xd8\xcb\x97\x86\x01\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\x08\xde\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\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\x04\x00#\xff\xf7\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^\x9e\xbd\xec\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}\xe7@\xfc\xa6\xaf\xc6\xec\xe8\xba\x19\xa3\x9b\x19vq\x91C\xa2\xe3\xde\x1f\xf1zB.\xf2\xc2\xc3,\x06\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x08\xde\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\x06\xf0[Y\xd3\xb2\x00\x00\xcdT/\x97BC\xb7\xdf\x85g\xcc\xe5\x15\xff\x1c\x05.6\xeen5+\x19;\xf4\xd9qS\xdfS\x18f\r|\xa7\xc1\xf9MW\xa1\xdb\xf9\x04\x9eL^\xf8\x84\n:\xbb\x8b\x8f\xd0\':\xbfO\xd9Y\xb7\xfc\x15\xa9:\xd2\xd2.\xca\x13f\xa4e\x9a\x07\xc8\x0by+\x930\xa0\xd6\xe6\xbf\x16\xfbB\xc9\x85\xdd\x97J\x93m\x1e\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\x00p\xc7\xd4\x8a3\x98\x00)\r0\xb7\x83!Z\xf9\x99\x95\xaeS\x1cI\xa9G\xa9\x85,\xb6z\xe7\x05\xcb\xaa\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\x00K\xbef\xce_\x84%\x14\x91BXD\x91\xe0w\xbc\xda\x04\x89\x84\x00Fk\xfd\x0f\xeez?H\x08\xe8\xa0\x08\xb9c\xf1\xc1\xcb\x96F\xf6d\xd9\xf0\xabL2k\x11\x7f\xad2\x99\xab7F\xff!\x81|\xa5\xf8\x06+Eo\x1d\x82\x11V\x1a\xa2\n;\xfe\xd6\x14{\xce\x1d\xce\xc1\xd4\xb8\xe6\xca\xfaG\xd8\x80\xdbk\x07Np\xef\x00\x00', # noqa: E501
|
||||
}
|
||||
|
||||
# test_constants["GENESIS_BLOCK"] = bytes(
|
||||
|
||||
@@ -1062,9 +1062,7 @@ class WalletNode:
|
||||
self.log.error("Additions request rejected")
|
||||
|
||||
@api_request
|
||||
async def respond_generator(
|
||||
self, response: wallet_protocol.RespondGenerator
|
||||
):
|
||||
async def respond_generator(self, response: wallet_protocol.RespondGenerator):
|
||||
"""
|
||||
The full node respond with transaction generator
|
||||
"""
|
||||
@@ -1072,9 +1070,7 @@ class WalletNode:
|
||||
self.log.info("generator received")
|
||||
|
||||
@api_request
|
||||
async def reject_generator(
|
||||
self, response: wallet_protocol.RejectGeneratorRequest
|
||||
):
|
||||
async def reject_generator(self, response: wallet_protocol.RejectGeneratorRequest):
|
||||
"""
|
||||
The full node rejected our request for generator
|
||||
"""
|
||||
|
||||
+172
-90
@@ -32,25 +32,8 @@ from src.util.ints import uint8, uint32, uint64, uint128, int512
|
||||
from src.util.hash import std_hash
|
||||
from src.util.path import mkdir
|
||||
from src.util.significant_bits import truncate_to_significant_bits
|
||||
|
||||
# Can't go much lower than 19, since plots start having no solutions
|
||||
from src.util.mempool_check_conditions import get_name_puzzle_conditions
|
||||
|
||||
k: uint8 = uint8(19)
|
||||
# Uses many plots for testing, in order to guarantee proofs of space at every height
|
||||
num_plots = 40
|
||||
# Use the empty string as the seed for the private key
|
||||
pool_sk: PrivateKey = PrivateKey.from_seed(b"")
|
||||
pool_pk: PublicKey = pool_sk.get_public_key()
|
||||
plot_sks: List[PrivateKey] = [
|
||||
PrivateKey.from_seed(pn.to_bytes(4, "big")) for pn in range(num_plots)
|
||||
]
|
||||
plot_pks: List[PublicKey] = [sk.get_public_key() for sk in plot_sks]
|
||||
|
||||
wallet_sk: PrivateKey = PrivateKey.from_seed(b"coinbase")
|
||||
coinbase_target = std_hash(bytes(wallet_sk.get_public_key()))
|
||||
fee_target = std_hash(bytes(wallet_sk.get_public_key()))
|
||||
n_wesolowski = uint8(0)
|
||||
from src.util.config import load_config, load_config_cli
|
||||
|
||||
|
||||
TEST_ROOT_PATH = Path(
|
||||
@@ -67,57 +50,106 @@ class BlockTools:
|
||||
Tools to generate blocks for testing.
|
||||
"""
|
||||
|
||||
def __init__(self, root_path: Path = TEST_ROOT_PATH):
|
||||
def __init__(
|
||||
self, root_path: Path = TEST_ROOT_PATH, real_plots: bool = False,
|
||||
):
|
||||
create_default_chia_config(root_path)
|
||||
initialize_ssl(root_path)
|
||||
self.root_path = root_path
|
||||
self.plot_config: Dict = {"plots": {}}
|
||||
self.pool_sk = pool_sk
|
||||
self.wallet_sk = wallet_sk
|
||||
self.wallet_sk: PrivateKey = PrivateKey.from_seed(b"coinbase")
|
||||
self.coinbase_target = std_hash(bytes(self.wallet_sk.get_public_key()))
|
||||
self.fee_target = std_hash(bytes(self.wallet_sk.get_public_key()))
|
||||
self.n_wesolowski = uint8(0)
|
||||
|
||||
plot_seeds: List[bytes32] = [
|
||||
ProofOfSpace.calculate_plot_seed(pool_pk, plot_pk) for plot_pk in plot_pks
|
||||
]
|
||||
self.plot_dir = self.root_path / "plots"
|
||||
mkdir(self.plot_dir)
|
||||
self.filenames: List[str] = [
|
||||
f"genesis-plots-{k}{std_hash(int.to_bytes(i, 4, 'big')).hex()}.dat"
|
||||
for i in range(num_plots)
|
||||
]
|
||||
done_filenames = set()
|
||||
temp_dir = self.plot_dir / "plot.tmp"
|
||||
mkdir(temp_dir)
|
||||
try:
|
||||
for pn, filename in enumerate(self.filenames):
|
||||
if not (self.plot_dir / filename).exists():
|
||||
plotter = DiskPlotter()
|
||||
plotter.create_plot_disk(
|
||||
str(self.plot_dir),
|
||||
str(self.plot_dir),
|
||||
filename,
|
||||
k,
|
||||
b"genesis",
|
||||
plot_seeds[pn],
|
||||
)
|
||||
done_filenames.add(filename)
|
||||
self.plot_config["plots"][str(self.plot_dir / filename)] = {
|
||||
"pool_pk": bytes(pool_pk).hex(),
|
||||
"sk": bytes(plot_sks[pn]).hex(),
|
||||
}
|
||||
except KeyboardInterrupt:
|
||||
for filename in self.filenames:
|
||||
if (
|
||||
filename not in done_filenames
|
||||
and (self.plot_dir / filename).exists()
|
||||
):
|
||||
(self.plot_dir / filename).unlink()
|
||||
sys.exit(1)
|
||||
if not real_plots:
|
||||
# No real plots supplied, so we will use the small test plots
|
||||
self.use_any_pos = True
|
||||
self.plot_config: Dict = {"plots": {}}
|
||||
# Can't go much lower than 19, since plots start having no solutions
|
||||
k: uint8 = uint8(19)
|
||||
# Uses many plots for testing, in order to guarantee proofs of space at every height
|
||||
num_plots = 40
|
||||
# Use the empty string as the seed for the private key
|
||||
pool_sk: PrivateKey = PrivateKey.from_seed(b"")
|
||||
pool_pk: PublicKey = pool_sk.get_public_key()
|
||||
plot_sks: List[PrivateKey] = [
|
||||
PrivateKey.from_seed(pn.to_bytes(4, "big")) for pn in range(num_plots)
|
||||
]
|
||||
plot_pks: List[PublicKey] = [sk.get_public_key() for sk in plot_sks]
|
||||
|
||||
@staticmethod
|
||||
def get_harvester_signature(header_data: HeaderData, plot_pk: PublicKey):
|
||||
for i, pk in enumerate(plot_pks):
|
||||
if pk == plot_pk:
|
||||
return plot_sks[i].sign_prepend(header_data.get_hash())
|
||||
plot_seeds: List[bytes32] = [
|
||||
ProofOfSpace.calculate_plot_seed(pool_pk, plot_pk)
|
||||
for plot_pk in plot_pks
|
||||
]
|
||||
plot_dir = root_path / "plots"
|
||||
mkdir(plot_dir)
|
||||
filenames: List[str] = [
|
||||
f"genesis-plots-{k}{std_hash(int.to_bytes(i, 4, 'big')).hex()}.dat"
|
||||
for i in range(num_plots)
|
||||
]
|
||||
done_filenames = set()
|
||||
temp_dir = plot_dir / "plot.tmp"
|
||||
mkdir(temp_dir)
|
||||
try:
|
||||
for pn, filename in enumerate(filenames):
|
||||
if not (plot_dir / filename).exists():
|
||||
plotter = DiskPlotter()
|
||||
plotter.create_plot_disk(
|
||||
str(plot_dir),
|
||||
str(plot_dir),
|
||||
filename,
|
||||
k,
|
||||
b"genesis",
|
||||
plot_seeds[pn],
|
||||
)
|
||||
done_filenames.add(filename)
|
||||
self.plot_config["plots"][str(plot_dir / filename)] = {
|
||||
"pool_pk": bytes(pool_pk).hex(),
|
||||
"sk": bytes(plot_sks[pn]).hex(),
|
||||
"pool_sk": bytes(pool_sk).hex(),
|
||||
}
|
||||
except KeyboardInterrupt:
|
||||
for filename in filenames:
|
||||
if (
|
||||
filename not in done_filenames
|
||||
and (plot_dir / filename).exists()
|
||||
):
|
||||
(plot_dir / filename).unlink()
|
||||
sys.exit(1)
|
||||
else:
|
||||
# Real plots supplied, so we will use these instead of the test plots
|
||||
config = load_config_cli(root_path, "config.yaml", "harvester")
|
||||
try:
|
||||
key_config = load_config(root_path, "keys.yaml")
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError("Keys not generated. Run `chia generate keys`")
|
||||
try:
|
||||
plot_config = load_config(root_path, "plots.yaml")
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError("Plots not generated. Run chia-create-plots")
|
||||
|
||||
pool_sks: List[PrivateKey] = [
|
||||
PrivateKey.from_bytes(bytes.fromhex(ce))
|
||||
for ce in key_config["pool_sks"]
|
||||
]
|
||||
|
||||
for key, value in plot_config["plots"].items():
|
||||
for pool_sk in pool_sks:
|
||||
if bytes(pool_sk.get_public_key()).hex() == value["pool_pk"]:
|
||||
plot_config["plots"][key]["pool_sk"] = bytes(pool_sk).hex()
|
||||
|
||||
self.plot_config = plot_config
|
||||
self.use_any_pos = False
|
||||
|
||||
def get_harvester_signature(self, header_data: HeaderData, plot_pk: PublicKey):
|
||||
for value_dict in self.plot_config["plots"].values():
|
||||
if (
|
||||
PrivateKey.from_bytes(bytes.fromhex(value_dict["sk"])).get_public_key()
|
||||
== plot_pk
|
||||
):
|
||||
return PrivateKey.from_bytes(
|
||||
bytes.fromhex(value_dict["sk"])
|
||||
).sign_prepend(header_data.get_hash())
|
||||
|
||||
def get_consecutive_blocks(
|
||||
self,
|
||||
@@ -297,7 +329,11 @@ class BlockTools:
|
||||
return block_list
|
||||
|
||||
def create_genesis_block(
|
||||
self, input_constants: Dict, challenge_hash=bytes([0] * 32), seed: bytes = b""
|
||||
self,
|
||||
input_constants: Dict,
|
||||
challenge_hash=bytes([0] * 32),
|
||||
seed: bytes = b"",
|
||||
reward_puzzlehash: Optional[bytes32] = None,
|
||||
) -> FullBlock:
|
||||
"""
|
||||
Creates the genesis block with the specified details.
|
||||
@@ -318,6 +354,7 @@ class BlockTools:
|
||||
uint64(test_constants["MIN_ITERS_STARTING"]),
|
||||
seed,
|
||||
True,
|
||||
reward_puzzlehash,
|
||||
)
|
||||
|
||||
def create_next_block(
|
||||
@@ -400,35 +437,69 @@ class BlockTools:
|
||||
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.
|
||||
"""
|
||||
prover = None
|
||||
plot_pk = None
|
||||
plot_sk = None
|
||||
qualities: List[bytes] = []
|
||||
for i in range(num_plots * 3):
|
||||
# Allow passing in seed, to create reorgs and different chains
|
||||
random.seed(seed + i.to_bytes(4, "big"))
|
||||
seeded_pn = random.randint(0, num_plots - 1)
|
||||
filename = self.filenames[seeded_pn]
|
||||
plot_pk = plot_pks[seeded_pn]
|
||||
plot_sk = plot_sks[seeded_pn]
|
||||
prover = DiskProver(str(self.plot_dir / filename))
|
||||
qualities = prover.get_qualities_for_challenge(challenge_hash)
|
||||
if len(qualities) > 0:
|
||||
break
|
||||
selected_prover = None
|
||||
selected_plot_sk = None
|
||||
selected_pool_sk = None
|
||||
selected_proof_index = 0
|
||||
plots = list(self.plot_config["plots"].items())
|
||||
selected_quality: Optional[bytes] = None
|
||||
best_quality = 0
|
||||
if self.use_any_pos:
|
||||
for i in range(len(plots) * 3):
|
||||
# Allow passing in seed, to create reorgs and different chains
|
||||
random.seed(seed + i.to_bytes(4, "big"))
|
||||
seeded_pn = random.randint(0, len(plots) - 1)
|
||||
pool_sk = PrivateKey.from_bytes(
|
||||
bytes.fromhex(plots[seeded_pn][1]["pool_sk"])
|
||||
)
|
||||
plot_sk = PrivateKey.from_bytes(
|
||||
bytes.fromhex(plots[seeded_pn][1]["sk"])
|
||||
)
|
||||
prover = DiskProver(plots[seeded_pn][0])
|
||||
qualities = prover.get_qualities_for_challenge(challenge_hash)
|
||||
if len(qualities) > 0:
|
||||
if self.use_any_pos:
|
||||
selected_quality = qualities[0]
|
||||
selected_prover = prover
|
||||
selected_pool_sk = pool_sk
|
||||
selected_plot_sk = plot_sk
|
||||
break
|
||||
else:
|
||||
for i in range(len(plots)):
|
||||
pool_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["pool_sk"]))
|
||||
plot_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["sk"]))
|
||||
prover = DiskProver(plots[i][0])
|
||||
qualities = prover.get_qualities_for_challenge(challenge_hash)
|
||||
j = 0
|
||||
for quality in qualities:
|
||||
qual_int = int.from_bytes(quality, "big", signed=False)
|
||||
if qual_int > best_quality:
|
||||
best_quality = qual_int
|
||||
selected_quality = quality
|
||||
selected_prover = prover
|
||||
selected_pool_sk = pool_sk
|
||||
selected_plot_sk = plot_sk
|
||||
selected_proof_index = j
|
||||
j += 1
|
||||
|
||||
assert prover
|
||||
assert plot_pk
|
||||
assert plot_sk
|
||||
if len(qualities) == 0:
|
||||
assert selected_prover
|
||||
assert selected_pool_sk
|
||||
assert selected_plot_sk
|
||||
pool_pk = selected_pool_sk.get_public_key()
|
||||
plot_pk = selected_plot_sk.get_public_key()
|
||||
if selected_quality is None:
|
||||
raise RuntimeError("No proofs for this challenge")
|
||||
|
||||
proof_xs: bytes = prover.get_full_proof(challenge_hash, 0)
|
||||
proof_xs: bytes = selected_prover.get_full_proof(
|
||||
challenge_hash, selected_proof_index
|
||||
)
|
||||
proof_of_space: ProofOfSpace = ProofOfSpace(
|
||||
challenge_hash, pool_pk, plot_pk, k, proof_xs
|
||||
challenge_hash, pool_pk, plot_pk, selected_prover.get_size(), proof_xs
|
||||
)
|
||||
number_iters: uint64 = pot_iterations.calculate_iterations(
|
||||
proof_of_space, difficulty, min_iters
|
||||
)
|
||||
# print("Doing iters", number_iters)
|
||||
int_size = (test_constants["DISCRIMINANT_SIZE_BITS"] + 16) >> 4
|
||||
|
||||
result = prove(
|
||||
@@ -444,11 +515,11 @@ class BlockTools:
|
||||
proof_bytes = result[2 * int_size : 4 * int_size]
|
||||
|
||||
proof_of_time = ProofOfTime(
|
||||
challenge_hash, number_iters, output, n_wesolowski, proof_bytes,
|
||||
challenge_hash, number_iters, output, self.n_wesolowski, proof_bytes,
|
||||
)
|
||||
|
||||
if not reward_puzzlehash:
|
||||
reward_puzzlehash = fee_target
|
||||
reward_puzzlehash = self.fee_target
|
||||
|
||||
# Use the extension data to create different blocks based on header hash
|
||||
extension_data: bytes32 = bytes32([random.randint(0, 255) for _ in range(32)])
|
||||
@@ -546,5 +617,16 @@ class BlockTools:
|
||||
# This might take a while, using the python VDF implementation.
|
||||
# Run by doing python -m tests.block_tools
|
||||
if __name__ == "__main__":
|
||||
bt = BlockTools()
|
||||
print(bytes(bt.create_genesis_block({}, bytes([1] * 32), b"0")))
|
||||
bt = BlockTools(real_plots=True)
|
||||
print(
|
||||
bytes(
|
||||
bt.create_genesis_block(
|
||||
{},
|
||||
bytes([12] * 32),
|
||||
b"0",
|
||||
bytes.fromhex(
|
||||
"a4259182b4d8e0af21331fc5be2681f953400b6726fa4095e3b91ae8f005a836"
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -154,7 +154,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -189,7 +189,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -227,7 +227,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -294,7 +294,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -343,7 +343,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -382,7 +382,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -401,7 +401,9 @@ class TestBlockValidation:
|
||||
blocks[9].header.data.height,
|
||||
blocks[9].header.data.coinbase.puzzle_hash,
|
||||
uint64(9991),
|
||||
bt.pool_sk,
|
||||
PrivateKey.from_bytes(
|
||||
bytes.fromhex(list(bt.plot_config["plots"].values())[0]["pool_sk"])
|
||||
),
|
||||
)
|
||||
new_header_data = HeaderData(
|
||||
blocks[9].header.data.height,
|
||||
@@ -428,7 +430,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
@@ -447,7 +449,9 @@ class TestBlockValidation:
|
||||
blocks[9].header.data.height,
|
||||
blocks[9].header.data.coinbase.puzzle_hash,
|
||||
uint64(9991),
|
||||
bt.pool_sk,
|
||||
PrivateKey.from_bytes(
|
||||
bytes.fromhex(list(bt.plot_config["plots"].values())[0]["pool_sk"])
|
||||
),
|
||||
)
|
||||
new_header_data = HeaderData(
|
||||
blocks[9].header.data.height,
|
||||
@@ -474,7 +478,7 @@ class TestBlockValidation:
|
||||
blocks[9].proof_of_time,
|
||||
Header(
|
||||
new_header_data,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
new_header_data, blocks[9].proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1137,7 +1137,7 @@ class TestBlockchainTransactions:
|
||||
next_block.proof_of_time,
|
||||
Header(
|
||||
bad_header,
|
||||
BlockTools.get_harvester_signature(
|
||||
bt.get_harvester_signature(
|
||||
bad_header, next_block.proof_of_space.plot_pubkey
|
||||
),
|
||||
),
|
||||
|
||||
@@ -65,6 +65,10 @@ class TestRpc:
|
||||
header = await client.get_header(state["lca"].header_hash)
|
||||
assert header == blocks[7].header
|
||||
|
||||
assert (await client.get_header_by_height(7)) == blocks[7].header
|
||||
|
||||
assert (await client.get_header_by_height(100)) is None
|
||||
|
||||
coins = await client.get_unspent_coins(
|
||||
blocks[-1].header.data.coinbase.puzzle_hash, blocks[-1].header_hash
|
||||
)
|
||||
|
||||
@@ -253,7 +253,9 @@ async def setup_harvester(port, dic={}):
|
||||
|
||||
async def setup_farmer(port, dic={}):
|
||||
config = load_config(root_path, "config.yaml", "farmer")
|
||||
pool_sk = bt.pool_sk
|
||||
pool_sk = blspy.PrivateKey.from_bytes(
|
||||
bytes.fromhex(list(bt.plot_config["plots"].values())[0]["pool_sk"])
|
||||
)
|
||||
pool_target = create_puzzlehash_for_pk(
|
||||
BLSPublicKey(bytes(pool_sk.get_public_key()))
|
||||
)
|
||||
|
||||
@@ -84,7 +84,7 @@ class TestWalletSimulator:
|
||||
funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, num_blocks - 2)
|
||||
for i in range(1, num_blocks - 1)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -115,7 +115,7 @@ class TestWalletSimulator:
|
||||
new_funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, (2 * num_blocks) - 2)
|
||||
for i in range(1, (2 * num_blocks) - 1)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -258,7 +258,7 @@ class TestWalletSimulator:
|
||||
funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, num_blocks - 2)
|
||||
for i in range(1, num_blocks - 1)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -291,7 +291,7 @@ class TestWalletSimulator:
|
||||
new_funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, num_blocks)
|
||||
for i in range(1, num_blocks + 1)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -340,7 +340,7 @@ class TestWalletSimulator:
|
||||
funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, num_blocks - 2)
|
||||
for i in range(1, num_blocks - 1)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -376,7 +376,7 @@ class TestWalletSimulator:
|
||||
new_funds = sum(
|
||||
[
|
||||
calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
|
||||
for i in range(0, num_blocks)
|
||||
for i in range(1, num_blocks + 1)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user