More changes
This commit is contained in:
parent
340c572f80
commit
0ac150a29b
13 changed files with 88 additions and 46 deletions
|
@ -6,6 +6,6 @@
|
|||
git submodule update --init --recursive
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip3 install .
|
||||
pip install .
|
||||
pip install lib/chiapos
|
||||
```
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
{
|
||||
"exclude": [ ".venv", "./lib"],
|
||||
"typingsPath": "./typestubs",
|
||||
"reportTypeshedErrors": false,
|
||||
"reportMissingImports": false,
|
||||
"reportMissingTypeStubs": false,
|
||||
"ignore": ["./src/server/server.py",
|
||||
"./src/util/streamable.py",
|
||||
"./src/util/byte_types.py"],
|
||||
"include": ["./src"],
|
||||
"pythonVersion": "3.7",
|
||||
|
||||
"executionEnvironments": [
|
||||
{
|
||||
"root": "./",
|
||||
"extraPaths": [
|
||||
"./lib"
|
||||
]
|
||||
}
|
||||
]
|
||||
"venvPath": ".",
|
||||
"venv": "./.venv",
|
||||
"reportMissingImports": false
|
||||
}
|
|
@ -1,25 +1,39 @@
|
|||
appnope==0.1.0
|
||||
atomicwrites==1.3.0
|
||||
attrs==19.1.0
|
||||
backcall==0.1.0
|
||||
bitstring==3.1.6
|
||||
blspy==0.1.9
|
||||
chiablockchain==0.2.1
|
||||
cbor2==4.1.2
|
||||
chiablockchain==0.1.1
|
||||
chiapos==0.2.1
|
||||
cppimport==18.11.8
|
||||
decorator==4.4.0
|
||||
entrypoints==0.3
|
||||
flake8==3.7.8
|
||||
importlib-metadata==0.18
|
||||
Mako==1.0.13
|
||||
ipython==7.6.1
|
||||
ipython-genutils==0.2.0
|
||||
jedi==0.14.1
|
||||
Mako==1.0.14
|
||||
MarkupSafe==1.1.1
|
||||
mccabe==0.6.1
|
||||
more-itertools==7.1.0
|
||||
more-itertools==7.2.0
|
||||
packaging==19.0
|
||||
parso==0.5.1
|
||||
pexpect==4.7.0
|
||||
pickleshare==0.7.5
|
||||
pluggy==0.12.0
|
||||
prompt-toolkit==2.0.9
|
||||
ptyprocess==0.6.0
|
||||
py==1.8.0
|
||||
pybind11==2.3.0
|
||||
pycodestyle==2.5.0
|
||||
pyflakes==2.1.1
|
||||
pyparsing==2.4.0
|
||||
Pygments==2.4.2
|
||||
pyparsing==2.4.1
|
||||
pytest==5.0.1
|
||||
six==1.12.0
|
||||
traitlets==4.3.2
|
||||
wcwidth==0.1.7
|
||||
zipp==0.5.2
|
||||
|
|
5
setup.py
5
setup.py
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/python3
|
||||
from setuptools import setup
|
||||
|
||||
dependencies = ['pytest', 'flake8', 'blspy==0.1.9']
|
||||
dependencies = ['blspy', 'cbor2']
|
||||
dev_dependencies = ['pytest', 'flake8', 'ipython']
|
||||
|
||||
setup(
|
||||
name='chiablockchain',
|
||||
|
@ -12,7 +13,7 @@ setup(
|
|||
license='Apache License',
|
||||
python_requires='>=3.7',
|
||||
keywords='chia blockchain node',
|
||||
install_requires=dependencies,
|
||||
install_requires=dependencies + dev_dependencies,
|
||||
long_description=open('README.md').read(),
|
||||
zip_safe=False,
|
||||
)
|
||||
|
|
|
@ -21,8 +21,9 @@ async def challenge_response(challenge_response: plotter_protocol.ChallengeRespo
|
|||
|
||||
quality = int.from_bytes(sha256(challenge_response.quality).digest(), "big")
|
||||
|
||||
# TODO: Check the real quality
|
||||
if quality < (2 ** 254):
|
||||
# TODO: Calculate the number of iterations using the difficulty, and compare to block time
|
||||
if quality < (2 ** 255):
|
||||
print("Good quality")
|
||||
# TODO: lookup the actual block hash
|
||||
block_hash = secrets.token_bytes(32)
|
||||
request = plotter_protocol.RequestProofOfSpace(challenge_response.challenge_hash,
|
||||
|
|
|
@ -3,8 +3,8 @@ import secrets
|
|||
import logging
|
||||
import os
|
||||
import os.path
|
||||
from typing import List
|
||||
from blspy import PrivateKey
|
||||
from typing import List, Optional
|
||||
from blspy import PrivateKey, PublicKey, InsecureSignature
|
||||
from chiapos import DiskPlotter, DiskProver
|
||||
from .util.api_decorators import api_request
|
||||
from .util.ints import uint32, uint8
|
||||
|
@ -22,6 +22,17 @@ plots = {}
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_quality_id(plot_seed: bytes32, index: uint8) -> uint32:
|
||||
return uint32(index + (int.from_bytes(plot_seed[:3], "big") << 8))
|
||||
|
||||
|
||||
def quality_id_matches(plot_seed: bytes32, quality_id: uint32) -> Optional[uint8]:
|
||||
index = uint8(quality_id % 256)
|
||||
if (int.from_bytes(plot_seed[:3], "big") << 8) != (quality_id - index):
|
||||
return None
|
||||
return index
|
||||
|
||||
|
||||
@api_request(plotter_handshake=plotter_protocol.PlotterHandshake.from_bin)
|
||||
async def plotter_handshake(plotter_handshake: plotter_protocol.PlotterHandshake,
|
||||
source_connection: ChiaConnection,
|
||||
|
@ -81,9 +92,22 @@ async def request_proof_of_space(request: plotter_protocol.RequestProofOfSpace,
|
|||
source_connection: ChiaConnection,
|
||||
all_connections: List[ChiaConnection] = []):
|
||||
log.info(f"Calling request_proof_of_space {request}")
|
||||
# TODO: Lookup private key, plot id
|
||||
pass
|
||||
for plot_seed, (sk, prover) in plots.items():
|
||||
# Using the response id, find the right plot and index from our solutions
|
||||
index: Optional[uint8] = quality_id_matches(plot_seed, request.response_id)
|
||||
if index is not None:
|
||||
proof_of_space: bytes = prover.get_full_proof(request.challenge_hash, index)
|
||||
|
||||
agg_pubkey = PublicKey.aggregate_insecure([pool_pubkey, sk.get_public_key()])
|
||||
# We use a basic "insecure" signature here, which can be aggregated with
|
||||
# the pools signature
|
||||
plotter_signature_share: InsecureSignature = sk.sign_insecure(
|
||||
agg_pubkey.serialize() + request.block_hash)
|
||||
|
||||
def get_quality_id(plot_seed: bytes32, index: uint8) -> uint32:
|
||||
return uint32(index + (int.from_bytes(plot_seed[:3], "big") << 8))
|
||||
response: plotter_protocol.ProofOfSpaceResponse = plotter_protocol.ProofOfSpaceResponse(
|
||||
request.block_hash,
|
||||
plotter_signature_share,
|
||||
proof_of_space
|
||||
)
|
||||
await source_connection.send("proof_of_space_response", response)
|
||||
return
|
||||
|
|
|
@ -3,6 +3,7 @@ import cbor2
|
|||
import logging
|
||||
from asyncio import IncompleteReadError
|
||||
from src.util.streamable import transform_to_streamable
|
||||
from asyncio.events import AbstractServer
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -37,8 +38,8 @@ class ChiaConnection:
|
|||
raise RuntimeError("This object already has open")
|
||||
self.open_ = True
|
||||
|
||||
peername = writer.get_extra_info('peername')
|
||||
log.info(f'Connected to {peername}')
|
||||
self.peername_ = writer.get_extra_info('peername')
|
||||
log.info(f'Connected to {self.peername_}')
|
||||
|
||||
try:
|
||||
while not reader.at_eof():
|
||||
|
@ -54,9 +55,9 @@ class ChiaConnection:
|
|||
if f is not None:
|
||||
await f(function_data, self, server_connections)
|
||||
else:
|
||||
log.error(f'Invalid message: {function} from {peername}')
|
||||
log.error(f'Invalid message: {function} from {self.peername_}')
|
||||
except IncompleteReadError:
|
||||
log.error("Received EOF, closing connection")
|
||||
log.error(f"Received EOF from {self.peername_}, closing connection")
|
||||
finally:
|
||||
writer.close()
|
||||
|
||||
|
@ -89,7 +90,7 @@ async def start_server(api, host: str, port: int):
|
|||
server_connections.append(connection)
|
||||
await connection.new_connection(reader, writer)
|
||||
|
||||
server = await asyncio.start_server(
|
||||
server: AbstractServer = await asyncio.start_server(
|
||||
callback, host, port)
|
||||
|
||||
addr = server.sockets[0].getsockname()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from blspy import PublicKey
|
||||
from typing import Any
|
||||
from ..util.streamable import streamable
|
||||
from ..util.ints import uint8
|
||||
|
||||
|
@ -11,7 +12,7 @@ class ProofOfSpace:
|
|||
proof: bytes
|
||||
|
||||
@classmethod
|
||||
def parse(cls, f):
|
||||
def parse(cls: Any, f):
|
||||
return cls(PublicKey.from_bytes(f.read(PublicKey.PUBLIC_KEY_SIZE)),
|
||||
PublicKey.from_bytes(f.read(PublicKey.PUBLIC_KEY_SIZE)),
|
||||
uint8.parse(f),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from blspy import PublicKey, PrependSignature
|
||||
from blspy import PublicKey, InsecureSignature
|
||||
from src.util.streamable import streamable
|
||||
from src.util.ints import uint32
|
||||
from src.types.sized_bytes import bytes32
|
||||
|
@ -35,7 +35,12 @@ class RequestProofOfSpace:
|
|||
|
||||
@streamable
|
||||
class ProofOfSpaceResponse:
|
||||
proof: ProofOfSpace
|
||||
block_hash: bytes32
|
||||
block_hash_signature: PrependSignature
|
||||
proof_of_possession: PrependSignature
|
||||
block_hash_signature_share: InsecureSignature
|
||||
proof: ProofOfSpace
|
||||
|
||||
@classmethod
|
||||
def parse(cls, f):
|
||||
return cls(f.read(32),
|
||||
InsecureSignature.from_bytes(f.read(InsecureSignature.SIGNATURE_SIZE)),
|
||||
f.read())
|
||||
|
|
|
@ -8,11 +8,11 @@ class bin_methods:
|
|||
Create "from_bin" and "as_bin" methods in terms of "parse" and "stream" methods.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bin(cls, blob: bytes) -> Any:
|
||||
def from_bin(cls: Any, blob: bytes) -> Any:
|
||||
f = io.BytesIO(blob)
|
||||
return cls.parse(f)
|
||||
|
||||
def as_bin(self) -> bytes:
|
||||
def as_bin(self: Any) -> bytes:
|
||||
f = io.BytesIO()
|
||||
self.stream(f)
|
||||
return bytes(f.getvalue())
|
||||
return bytes(f.getvalue())
|
||||
|
|
|
@ -16,6 +16,7 @@ def make_sized_bytes(size):
|
|||
v = bytes(v)
|
||||
if not isinstance(v, bytes) or len(v) != size:
|
||||
raise ValueError("bad %s initializer %s" % (name, v))
|
||||
print("Creating new bytesl", self, v)
|
||||
return bytes.__new__(self, v)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import dataclasses
|
||||
|
||||
from typing import Type, BinaryIO, get_type_hints
|
||||
from typing import Type, BinaryIO, get_type_hints, Any
|
||||
|
||||
from .bin_methods import bin_methods
|
||||
|
||||
|
||||
def streamable(cls):
|
||||
def streamable(cls: Any):
|
||||
"""
|
||||
This is a decorator for class definitions. It applies the dataclasses.dataclass
|
||||
decorator, and also allows fields to be cast to their expected type. The resulting
|
||||
|
@ -55,7 +55,7 @@ def streamable(cls):
|
|||
else:
|
||||
raise NotImplementedError(f"can't stream {v}, {f_name}")
|
||||
|
||||
cls1 = dataclasses.dataclass(_cls=cls, frozen=True, init=False)
|
||||
cls1 = dataclasses.dataclass(_cls=cls, init=False, frozen=True)
|
||||
|
||||
cls2 = type(cls.__name__, (cls1, bin_methods, _local), {})
|
||||
return cls2
|
||||
|
|
|
@ -6,11 +6,12 @@ from .bin_methods import bin_methods
|
|||
|
||||
|
||||
class struct_stream(bin_methods):
|
||||
PACK = ""
|
||||
"""
|
||||
Create a class that can parse and stream itself based on a struct.pack template string.
|
||||
"""
|
||||
@classmethod
|
||||
def parse(cls, f: BinaryIO) -> Any:
|
||||
def parse(cls: Any, f: BinaryIO) -> Any:
|
||||
return cls(*struct.unpack(cls.PACK, f.read(struct.calcsize(cls.PACK))))
|
||||
|
||||
def stream(self, f):
|
||||
|
|
Loading…
Reference in a new issue