Merge
This commit is contained in:
commit
a22e606f75
|
@ -5,6 +5,8 @@ __pycache__/
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
**/*.o
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
|
|
|
@ -8,6 +8,11 @@ Python 3.7 is used for this project.
|
||||||
sudo apt-get install build-essential cmake python3-dev --no-install-recommends
|
sudo apt-get install build-essential cmake python3-dev --no-install-recommends
|
||||||
|
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
cd lib/chiavdf
|
||||||
|
# Install libgmp, libboost, and libflint, and then run the following
|
||||||
|
sh install.sh
|
||||||
|
|
||||||
python3 -m venv .venv
|
python3 -m venv .venv
|
||||||
. .venv/bin/activate
|
. .venv/bin/activate
|
||||||
pip install wheel
|
pip install wheel
|
||||||
|
@ -18,6 +23,7 @@ pip install lib/chiapos
|
||||||
### Run servers
|
### Run servers
|
||||||
Run the servers in the following order (you can also use ipython):
|
Run the servers in the following order (you can also use ipython):
|
||||||
```bash
|
```bash
|
||||||
|
./lib/chiavdf/fast_vdf/vdf 8889
|
||||||
python -m src.server.start_plotter
|
python -m src.server.start_plotter
|
||||||
python -m src.server.start_timelord
|
python -m src.server.start_timelord
|
||||||
python -m src.server.start_farmer
|
python -m src.server.start_farmer
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 28942e66fda6397443aa33c0cb6515d8e8b991e7
|
Subproject commit 6a5570ba4d1b71d8e0e8e3f7e19acb898d601ff5
|
|
@ -361,8 +361,8 @@ class Blockchain:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 4. Check PoT
|
# 4. Check PoT
|
||||||
#TODO(Florin): Change the hardcode of the genesis with new pot format.
|
# TODO(Florin): Change the hardcode of the genesis with new pot format.
|
||||||
if not block.trunk_block.proof_of_time.is_valid(self.constants["DISCRIMINANT_SIZE_BITS"]) and not genesis:
|
if not block.trunk_block.proof_of_time.is_valid(self.constants["DISCRIMINANT_SIZE_BITS"]):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if block.body.coinbase.height != block.trunk_block.challenge.height:
|
if block.body.coinbase.height != block.trunk_block.challenge.height:
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -627,4 +627,3 @@ async def block(block: peer_protocol.Block) -> AsyncGenerator[OutboundMessage, N
|
||||||
timelord_request_end = timelord_protocol.ChallengeStart(block.block.trunk_block.proof_of_time.
|
timelord_request_end = timelord_protocol.ChallengeStart(block.block.trunk_block.proof_of_time.
|
||||||
output.challenge_hash)
|
output.challenge_hash)
|
||||||
yield OutboundMessage(NodeType.TIMELORD, Message("challenge_end", timelord_request_end), Delivery.BROADCAST)
|
yield OutboundMessage(NodeType.TIMELORD, Message("challenge_end", timelord_request_end), Delivery.BROADCAST)
|
||||||
|
|
||||||
|
|
|
@ -197,19 +197,19 @@ async def initialize_pipeline(aiter,
|
||||||
handshake_finished_3 = forker.fork(is_active=True)
|
handshake_finished_3 = forker.fork(is_active=True)
|
||||||
|
|
||||||
# Reads messages one at a time from the TCP connection
|
# Reads messages one at a time from the TCP connection
|
||||||
messages_aiter = join_aiters(parallel_map_aiter(connection_to_message, 100, handshake_finished_1))
|
messages_aiter = join_aiters(parallel_map_aiter(connection_to_message, handshake_finished_1, 100))
|
||||||
|
|
||||||
# Handles each message one at a time, and yields responses to send back or broadcast
|
# Handles each message one at a time, and yields responses to send back or broadcast
|
||||||
responses_aiter = join_aiters(parallel_map_aiter(
|
responses_aiter = join_aiters(parallel_map_aiter(
|
||||||
partial_func.partial_async_gen(handle_message, api),
|
partial_func.partial_async_gen(handle_message, api),
|
||||||
100, messages_aiter))
|
messages_aiter, 100))
|
||||||
|
|
||||||
if on_connect is not None:
|
if on_connect is not None:
|
||||||
# Uses a forked aiter, and calls the on_connect function to send some initial messages
|
# Uses a forked aiter, and calls the on_connect function to send some initial messages
|
||||||
# as soon as the connection is established
|
# as soon as the connection is established
|
||||||
|
|
||||||
on_connect_outbound_aiter = join_aiters(parallel_map_aiter(
|
on_connect_outbound_aiter = join_aiters(parallel_map_aiter(
|
||||||
partial_func.partial_async_gen(connection_to_outbound, on_connect), 100, handshake_finished_2))
|
partial_func.partial_async_gen(connection_to_outbound, on_connect), handshake_finished_2, 100))
|
||||||
|
|
||||||
responses_aiter = join_aiters(iter_to_aiter([responses_aiter, on_connect_outbound_aiter]))
|
responses_aiter = join_aiters(iter_to_aiter([responses_aiter, on_connect_outbound_aiter]))
|
||||||
if outbound_aiter is not None:
|
if outbound_aiter is not None:
|
||||||
|
@ -220,7 +220,7 @@ async def initialize_pipeline(aiter,
|
||||||
|
|
||||||
# For each outbound message, replicate for each peer that we need to send to
|
# For each outbound message, replicate for each peer that we need to send to
|
||||||
expanded_messages_aiter = join_aiters(parallel_map_aiter(
|
expanded_messages_aiter = join_aiters(parallel_map_aiter(
|
||||||
expand_outbound_messages, 100, responses_aiter))
|
expand_outbound_messages, responses_aiter, 100))
|
||||||
|
|
||||||
# This will run forever. Sends each message through the TCP connection, using the
|
# This will run forever. Sends each message through the TCP connection, using the
|
||||||
# length encoding and CBOR serialization
|
# length encoding and CBOR serialization
|
||||||
|
|
|
@ -7,6 +7,7 @@ from src import timelord
|
||||||
|
|
||||||
logging.basicConfig(format='Timelord %(name)-25s: %(levelname)-20s %(message)s', level=logging.INFO)
|
logging.basicConfig(format='Timelord %(name)-25s: %(levelname)-20s %(message)s', level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
host, port = parse_host_port(timelord)
|
host, port = parse_host_port(timelord)
|
||||||
server, _ = await start_chia_server(host, port, timelord, NodeType.FULL_NODE)
|
server, _ = await start_chia_server(host, port, timelord, NodeType.FULL_NODE)
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
|
||||||
import io
|
import io
|
||||||
import sys
|
|
||||||
import yaml
|
import yaml
|
||||||
from asyncio import Lock
|
from asyncio import Lock
|
||||||
from typing import Dict
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from lib.chiavdf.inkfish.create_discriminant import create_discriminant
|
from lib.chiavdf.inkfish.create_discriminant import create_discriminant
|
||||||
from lib.chiavdf.inkfish.proof_of_time import check_proof_of_time_nwesolowski
|
from lib.chiavdf.inkfish.proof_of_time import check_proof_of_time_nwesolowski
|
||||||
|
@ -18,6 +16,7 @@ from src.util.ints import uint8
|
||||||
from src.consensus.constants import constants
|
from src.consensus.constants import constants
|
||||||
from src.server.outbound_message import OutboundMessage, Delivery, Message, NodeType
|
from src.server.outbound_message import OutboundMessage, Delivery, Message, NodeType
|
||||||
|
|
||||||
|
|
||||||
class Database:
|
class Database:
|
||||||
lock: Lock = Lock()
|
lock: Lock = Lock()
|
||||||
free_servers = []
|
free_servers = []
|
||||||
|
@ -25,11 +24,13 @@ class Database:
|
||||||
active_discriminants: Dict = {}
|
active_discriminants: Dict = {}
|
||||||
done_discriminants = []
|
done_discriminants = []
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
config = yaml.safe_load(open("src/config/timelord.yaml", "r"))
|
config = yaml.safe_load(open("src/config/timelord.yaml", "r"))
|
||||||
db = Database()
|
db = Database()
|
||||||
db.free_servers.append(8889)
|
db.free_servers.append(8889)
|
||||||
|
|
||||||
|
|
||||||
@api_request
|
@api_request
|
||||||
async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
"""
|
"""
|
||||||
|
@ -37,7 +38,7 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
should be started on it. We can generate a classgroup (discriminant), and start
|
should be started on it. We can generate a classgroup (discriminant), and start
|
||||||
a new VDF process here. But we don't know how many iterations to run for, so we run
|
a new VDF process here. But we don't know how many iterations to run for, so we run
|
||||||
forever.
|
forever.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
disc: int = create_discriminant(challenge_start.challenge_hash, constants["DISCRIMINANT_SIZE_BITS"])
|
disc: int = create_discriminant(challenge_start.challenge_hash, constants["DISCRIMINANT_SIZE_BITS"])
|
||||||
|
|
||||||
|
@ -46,19 +47,19 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
log.info("This discriminant was already done..")
|
log.info("This discriminant was already done..")
|
||||||
return
|
return
|
||||||
|
|
||||||
#Wait for a server to become free.
|
# Wait for a server to become free.
|
||||||
port = None
|
port: Optional[int] = None
|
||||||
while (port is None):
|
while (port is None):
|
||||||
async with db.lock:
|
async with db.lock:
|
||||||
if (len(db.free_servers) != 0):
|
if (len(db.free_servers) != 0):
|
||||||
port = db.free_servers[0]
|
port = db.free_servers[0]
|
||||||
db.free_servers = db.free_servers[1:]
|
db.free_servers = db.free_servers[1:]
|
||||||
log.info(f"Discriminant {disc} attached to port {port}.")
|
log.info(f"Discriminant {disc} attached to port {port}.")
|
||||||
#Poll until a server becomes free.
|
# Poll until a server becomes free.
|
||||||
if (port is None):
|
if (port is None):
|
||||||
await asyncio.sleep(3)
|
await asyncio.sleep(3)
|
||||||
|
|
||||||
#TODO(Florin): Handle connection failure (attempt another server)
|
# TODO(Florin): Handle connection failure (attempt another server)
|
||||||
try:
|
try:
|
||||||
reader, writer = await asyncio.open_connection('127.0.0.1', port)
|
reader, writer = await asyncio.open_connection('127.0.0.1', port)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -70,17 +71,17 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
|
|
||||||
ok = await reader.readexactly(2)
|
ok = await reader.readexactly(2)
|
||||||
assert(ok.decode() == "OK")
|
assert(ok.decode() == "OK")
|
||||||
|
|
||||||
log.info("Got handshake with VDF server.")
|
log.info("Got handshake with VDF server.")
|
||||||
|
|
||||||
async with db.lock:
|
async with db.lock:
|
||||||
db.active_discriminants[challenge_start.challenge_hash] = writer
|
db.active_discriminants[challenge_start.challenge_hash] = writer
|
||||||
|
|
||||||
#Listen to the server until "STOP" is received.
|
# Listen to the server until "STOP" is received.
|
||||||
while(True):
|
while True:
|
||||||
data = await reader.readexactly(4)
|
data = await reader.readexactly(4)
|
||||||
if (data.decode() == "STOP"):
|
if (data.decode() == "STOP"):
|
||||||
#Server is now available.
|
# Server is now available.
|
||||||
async with db.lock:
|
async with db.lock:
|
||||||
writer.write(b"ACK")
|
writer.write(b"ACK")
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
|
@ -88,7 +89,7 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
#This must be a proof, read the continuation.
|
# This must be a proof, read the continuation.
|
||||||
proof = await reader.readexactly(1860)
|
proof = await reader.readexactly(1860)
|
||||||
stdout_bytes_io: io.BytesIO = io.BytesIO(bytes.fromhex(data.decode() + proof.decode()))
|
stdout_bytes_io: io.BytesIO = io.BytesIO(bytes.fromhex(data.decode() + proof.decode()))
|
||||||
iterations_needed = int.from_bytes(stdout_bytes_io.read(8), "big", signed=True)
|
iterations_needed = int.from_bytes(stdout_bytes_io.read(8), "big", signed=True)
|
||||||
|
@ -101,13 +102,13 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
assert check_proof_of_time_nwesolowski(disc, x, proof_blob, iterations_needed, 1024, 2)
|
assert check_proof_of_time_nwesolowski(disc, x, proof_blob, iterations_needed, 1024, 2)
|
||||||
|
|
||||||
output = ProofOfTimeOutput(challenge_start.challenge_hash,
|
output = ProofOfTimeOutput(challenge_start.challenge_hash,
|
||||||
iterations_needed,
|
iterations_needed,
|
||||||
ClassgroupElement(y.a, y.b))
|
ClassgroupElement(y.a, y.b))
|
||||||
proof_of_time = ProofOfTime(output, config['n_wesolowski'], [uint8(b) for b in proof_bytes])
|
proof_of_time = ProofOfTime(output, config['n_wesolowski'], [uint8(b) for b in proof_bytes])
|
||||||
response = timelord_protocol.ProofOfTimeFinished(proof_of_time)
|
response = timelord_protocol.ProofOfTimeFinished(proof_of_time)
|
||||||
|
|
||||||
log.info(f"Got PoT for challenge {challenge_start.challenge_hash}")
|
log.info(f"Got PoT for challenge {challenge_start.challenge_hash}")
|
||||||
#async with db.lock:
|
# async with db.lock:
|
||||||
# if (challenge_start.challenge_hash in db.solved_discriminants):
|
# if (challenge_start.challenge_hash in db.solved_discriminants):
|
||||||
# log.info("I've already propagated one proof... Ignoring for now...")
|
# log.info("I've already propagated one proof... Ignoring for now...")
|
||||||
# continue
|
# continue
|
||||||
|
@ -117,7 +118,7 @@ async def challenge_start(challenge_start: timelord_protocol.ChallengeStart):
|
||||||
e_to_str = str(e)
|
e_to_str = str(e)
|
||||||
log.error(f"Socket error: {e_to_str}")
|
log.error(f"Socket error: {e_to_str}")
|
||||||
|
|
||||||
|
|
||||||
@api_request
|
@api_request
|
||||||
async def challenge_end(challenge_end: timelord_protocol.ChallengeEnd):
|
async def challenge_end(challenge_end: timelord_protocol.ChallengeEnd):
|
||||||
"""
|
"""
|
||||||
|
@ -126,7 +127,7 @@ async def challenge_end(challenge_end: timelord_protocol.ChallengeEnd):
|
||||||
"""
|
"""
|
||||||
async with db.lock:
|
async with db.lock:
|
||||||
if (challenge_end.challenge_hash in db.done_discriminants):
|
if (challenge_end.challenge_hash in db.done_discriminants):
|
||||||
return
|
return
|
||||||
if (challenge_end.challenge_hash in db.active_discriminants):
|
if (challenge_end.challenge_hash in db.active_discriminants):
|
||||||
writer = db.active_discriminants[challenge_end.challenge_hash]
|
writer = db.active_discriminants[challenge_end.challenge_hash]
|
||||||
writer.write(b'10')
|
writer.write(b'10')
|
||||||
|
@ -135,6 +136,7 @@ async def challenge_end(challenge_end: timelord_protocol.ChallengeEnd):
|
||||||
db.done_discriminants.append(challenge_end.challenge_hash)
|
db.done_discriminants.append(challenge_end.challenge_hash)
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
@api_request
|
@api_request
|
||||||
async def proof_of_space_info(proof_of_space_info: timelord_protocol.ProofOfSpaceInfo):
|
async def proof_of_space_info(proof_of_space_info: timelord_protocol.ProofOfSpaceInfo):
|
||||||
"""
|
"""
|
||||||
|
@ -143,15 +145,15 @@ async def proof_of_space_info(proof_of_space_info: timelord_protocol.ProofOfSpac
|
||||||
many iterations to run for. TODO: process should be started in challenge_start instead.
|
many iterations to run for. TODO: process should be started in challenge_start instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
while (True):
|
while True:
|
||||||
async with db.lock:
|
async with db.lock:
|
||||||
if (proof_of_space_info.challenge_hash in db.active_discriminants):
|
if (proof_of_space_info.challenge_hash in db.active_discriminants):
|
||||||
writer = db.active_discriminants[proof_of_space_info.challenge_hash]
|
writer = db.active_discriminants[proof_of_space_info.challenge_hash]
|
||||||
writer.write((str(len(str(proof_of_space_info.iterations_needed)))
|
writer.write((str(len(str(proof_of_space_info.iterations_needed)))
|
||||||
+ str(proof_of_space_info.iterations_needed)).encode())
|
+ str(proof_of_space_info.iterations_needed)).encode())
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
return
|
return
|
||||||
if (proof_of_space_info.challenge_hash in db.done_discriminants):
|
if (proof_of_space_info.challenge_hash in db.done_discriminants):
|
||||||
log.info("Got iters for a finished challenge")
|
log.info("Got iters for a finished challenge")
|
||||||
return
|
return
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
|
|
|
@ -208,5 +208,5 @@ class BlockTools:
|
||||||
|
|
||||||
|
|
||||||
# print(create_genesis_block().serialize())
|
# print(create_genesis_block().serialize())
|
||||||
# bt = BlockTools()
|
bt = BlockTools()
|
||||||
# print(bt.create_genesis_block(bytes([4]*32)).serialize())
|
print(bt.create_genesis_block(bytes([4]*32)).serialize())
|
||||||
|
|
Loading…
Reference in New Issue