More changes

This commit is contained in:
Mariano Sorgente 2019-07-23 23:11:07 +09:00
parent 340c572f80
commit 0ac150a29b
13 changed files with 88 additions and 46 deletions

View file

@ -6,6 +6,6 @@
git submodule update --init --recursive
python3 -m venv .venv
. .venv/bin/activate
pip3 install .
pip install .
pip install lib/chiapos
```

View file

@ -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
}

View file

@ -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

View file

@ -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,
)

View file

@ -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,

View file

@ -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

View file

@ -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()

View file

@ -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),

View file

@ -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())

View file

@ -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())

View file

@ -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

View file

@ -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

View file

@ -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):