Select Git revision
-
* Fix distance-oracle EvaluationPool type * Remove instanciation and dep to certification * Doc comments, make max size params const * Fix default distance dir * Rename pool accessors * doc add READMEs * fix(distance): Remember account_id who reserved * Log, comments, crate author * feat: distance * integration tests, expiration * fixes & working end2end tests * fix(distance): max_depth, compute min_certs_for_referee * fix(distance): add distance pallet to gtest, g1 * test(distance): WiP end2end test * feat: distance
* Fix distance-oracle EvaluationPool type * Remove instanciation and dep to certification * Doc comments, make max size params const * Fix default distance dir * Rename pool accessors * doc add READMEs * fix(distance): Remember account_id who reserved * Log, comments, crate author * feat: distance * integration tests, expiration * fixes & working end2end tests * fix(distance): max_depth, compute min_certs_for_referee * fix(distance): add distance pallet to gtest, g1 * test(distance): WiP end2end test * feat: distance
node.py 15.90 KiB
import attr
from duniterpy.documents import Peer, BMAEndpoint, BlockUID
from duniterpy.api import errors
from duniterpy.key import SigningKey, ScryptParams
from .http import HTTPServer
from .block_forge import BlockForge
import logging
@attr.s()
class Node:
http = attr.ib()
forge = attr.ib()
_logger = attr.ib(default=attr.Factory(lambda: logging.getLogger('mirage')))
@classmethod
async def start(cls, port, currency, salt, password, loop):
key = SigningKey(salt, password, ScryptParams(2 ** 12, 16, 1))
node = cls(HTTPServer(port, loop), BlockForge(currency, key))
get_routes = {
'/network/peering': node.peering,
'/blockchain/block/{number}': node.block_by_number,
'/blockchain/current': node.current_block,
'/tx/sources/{pubkey}': node.sources,
'/wot/lookup/{search}': node.lookup,
'/wot/certifiers-of/{search}': node.certifiers_of,
'/wot/certified-by/{search}': node.certified_by,
'/blockchain/parameters': node.parameters,
'/blockchain/with/ud': node.with_ud,
'/blockchain/memberships/{search}': node.memberships,
'/tx/history/{search}': node.tx_history,
}
for r, h in get_routes.items():
node.http.add_route("GET", r, h)
srv, port, url = await node.http.create_server()
print("Server started on {0}".format(url))
return node
def block_by_number(self, request):
number = int(request.match_info['number'])
try:
block = self.forge.blocks[number]
return {
"version": block.version,
"nonce": block.noonce,
"number": block.number,
"powMin": block.powmin,
"time": block.time,
"medianTime": block.mediantime,
"membersCount": block.members_count,
"monetaryMass": self.forge.monetary_mass(),
"unitbase": block.unit_base,
"issuersCount": block.different_issuers_count,
"issuersFrame": block.issuers_frame,
"issuersFrameVar": block.issuers_frame_var,
"currency": block.currency,
"issuer": block.issuer,
"signature": block.signatures[0],
"hash": block.sha_hash,
"parameters": block.parameters if block.parameters else "",
"previousHash": block.prev_hash,
"previousIssuer": block.prev_issuer,
"inner_hash": block.inner_hash,
"dividend": block.ud,
"identities": [i.inline() for i in block.identities],
"joiners": [m.inline() for m in block.joiners],
"actives": [m.inline() for m in block.actives],
"leavers": [m.inline() for m in block.leavers],
"revoked": [r.inline() for r in block.revoked],
"excluded": [i.inline() for i in block.excluded],
"certifications": [c.inline() for c in block.certifications],
"transactions": [t.inline() for t in block.transactions],
"raw": block.raw()
}, 200
except IndexError:
return {
"ucode": errors.BLOCK_NOT_FOUND,
"message": "Block not found"
}, 404
def current_block(self, request):
try:
block = self.forge.blocks[-1]
return {
"version": block.version,
"nonce": block.noonce,
"number": block.number,
"powMin": block.powmin,
"time": block.time,
"medianTime": block.mediantime,
"membersCount": block.members_count,
"monetaryMass": self.forge.monetary_mass(),
"unitbase": block.unit_base,
"issuersCount": block.different_issuers_count,
"issuersFrame": block.issuers_frame,
"issuersFrameVar": block.issuers_frame_var,
"currency": block.currency,
"issuer": block.issuer,
"signature": block.signatures[0],
"hash": block.computed_inner_hash(),
"parameters": block.parameters if block.parameters else "",
"previousHash": block.prev_hash,
"previousIssuer": block.prev_issuer,
"inner_hash": block.inner_hash,
"dividend": block.ud,
"identities": [ i.inline() for i in block.identities],
"joiners": [m.inline() for m in block.joiners],
"actives": [m.inline() for m in block.actives],
"leavers": [m.inline() for m in block.leavers],
"revoked": [r.inline() for r in block.revoked],
"excluded": [i.inline() for i in block.excluded],
"certifications": [c.inline() for c in block.certifications],
"transactions": [t.inline() for t in block.transactions],
"raw": block.raw()
}, 200
except IndexError:
return {
"ucode": errors.NO_CURRENT_BLOCK,
"message": "No current block"
}, 404
def sources(self, request):
pubkey = str(request.match_info['pubkey'])
try:
sources = self.forge.user_identities[pubkey].sources
return {
"currency": self.forge.currency,
"pubkey": pubkey,
"sources": [{
'type': s.source,
'noffset': s.index,
'identifier': s.origin_id,
'amount': s.amount,
'base': s.base
} for s in sources]
}, 200
except IndexError:
return {
"currency": self.forge.currency,
"pubkey": pubkey,
"sources": []
}, 200
def peering(self, request):
return {
"version": 2,
"currency": self.peer_doc().currency,
"endpoints": [
str(self.peer_doc().endpoints[0])
],
"status": "UP",
"block": str(self.peer_doc().blockUID),
"signature": self.peer_doc().signatures[0],
"raw": self.peer_doc().raw(),
"pubkey": self.peer_doc().pubkey
}, 200
def parameters(self, request):
return {
"currency": self.forge.currency,
"c": 0.0025,
"dt": 86400,
"ud0": 100000,
"sigPeriod": 10800,
"sigStock": 40,
"sigWindow": 2629800,
"sigValidity": 31557600,
"sigQty": 1,
"idtyWindow": 604800,
"msWindow": 604800,
"xpercent": 0.9,
"msValidity": 15778800,
"stepMax": 5,
"medianTimeBlocks": 12,
"avgGenTime": 300,
"dtDiffEval": 25,
"blocksRot": 40,
"percentRot": 0.66
}, 200
def with_ud(self, request):
return {
"result": {
"blocks": [b.number for b in self.forge.blocks if b.ud]
}
}, 200
def memberships(self, request):
search = str(request.match_info['search'])
try:
user_identity = self.forge.user_identities[search]
except KeyError:
try:
user_identity = next(i for i in self.forge.user_identities.values() if i.uid == search)
except StopIteration:
return {
'error': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
'message': "No member matching this pubkey or uid"
}, 200
return {
"pubkey": user_identity.pubkey,
"uid": user_identity.uid,
"sigDate": str(user_identity.blockstamp),
"memberships": [
{
"version": 2,
"currency": self.forge.currency,
"membership": m.type,
"blockNumber": m.blockstamp.number,
"blockHash": m.blockstamp.sha_hash,
"written": m.written_on
}
for m in user_identity.memberships
]
}, 200
def certifiers_of(self, request):
search = str(request.match_info['search'])
try:
user_identity = self.forge.user_identities[search]
except KeyError:
try:
user_identity = next(i for i in self.forge.user_identities.values() if i.uid == search)
except StopIteration:
return {
'error': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
'message': "No member matching this pubkey or uid"
}, 200
return {
"pubkey": user_identity.pubkey,
"uid": user_identity.uid,
"sigDate": str(user_identity.blockstamp),
"isMember": user_identity.member,
"certifications": [
{
"pubkey": c.from_identity.pubkey,
"uid": c.from_identity.uid,
"isMember": c.from_identity.member,
"wasMember": c.from_identity.was_member,
"cert_time": {
"block": c.block,
"medianTime": c.mediantime
},
"sigDate": str(c.from_identity.blockstamp),
"written": {
"number": c.written_on.number,
"hash": c.written_on.sha_hash
},
"signature": c.signature
}
for c in user_identity.certs_received
]
}, 200
def certified_by(self, request):
search = str(request.match_info['search'])
try:
user_identity = self.forge.user_identities[search]
except KeyError:
try:
user_identity = next(i for i in self.forge.user_identities.values() if i.uid == search)
except StopIteration:
return {
'error': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
'message': "No member matching this pubkey or uid"
}, 200
return {
"pubkey": user_identity.pubkey,
"uid": user_identity.uid,
"sigDate": str(user_identity.blockstamp),
"isMember": user_identity.member,
"certifications": [
{
"pubkey": c.from_identity.pubkey,
"uid": c.from_identity.uid,
"isMember": c.from_identity.member,
"wasMember": c.from_identity.was_member,
"cert_time": {
"block": c.block,
"medianTime": c.mediantime
},
"sigDate": str(c.from_identity.blockstamp),
"written": {
"number": c.written_on.number,
"hash": c.written_on.sha_hash
},
"signature": c.signature
}
for c in user_identity.certs_sent
]
}, 200
def lookup(self, request):
search = str(request.match_info['search'])
matched = [i for i in self.forge.user_identities.values() if search in i.pubkey or search in i.uid]
return {
"partial": False,
"results": [
{
"pubkey": m.pubkey,
"uid": m.uid,
"meta": {
"timestamp": str(m.blockstamp),
},
"revoked": m.revoked,
"revoked_on": m.revoked_on,
"revocation_sig": m.revocation_sig,
"self": m.signature,
"others": [
{
"pubkey": c.to_identity.pubkey,
"meta": {
"block_number": c.block,
},
"uids": [c.to_identity.uid],
"isMember": c.to_identity.member,
"wasMember": c.to_identity.was_member,
"signature": c.signature
} for c in m.certs_received
],
"signed": [
{
"pubkey": c.to_identity.pubkey,
"meta": {
"block_number": c.block,
},
"uids": [c.to_identity.uid],
"isMember": c.to_identity.member,
"wasMember": c.to_identity.was_member,
"signature": c.signature
} for c in m.certs_sent
]
}
for m in matched
]
}, 200
def tx_history(self, request):
search = str(request.match_info['search'])
try:
user_identity = self.forge.user_identities[search]
except KeyError:
try:
user_identity = next(i for i in self.forge.user_identities.values() if i.uid == search)
except StopIteration:
return {
'error': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
'message': "No member matching this pubkey or uid"
}, 200
return {
"currency": self.forge.currency,
"pubkey": user_identity.pubkey,
"history": {
"sent": [
{
"version": 2,
"issuers": tx.issuers,
"inputs": [i.inline() for i in tx.inputs],
"unlocks": [u.inline() for u in tx.unlocks],
"outputs": [o.inline() for o in tx.outputs],
"comment": tx.comment,
"locktime": tx.locktime,
"blockstamp": str(tx.blockstamp),
"blockstampTime": next([b.medianTime for b in self.forge.blocks
if b.number == tx.blockstamp.number]),
"signatures": tx.signatures
}
for tx in user_identity.tx_sent
],
"received": [
{
"version": 2,
"issuers": tx.issuers,
"inputs": [i.inline() for i in tx.inputs],
"unlocks": [u.inline() for u in tx.unlocks],
"outputs": [o.inline() for o in tx.outputs],
"comment": tx.comment,
"locktime": tx.locktime,
"blockstamp": str(tx.blockstamp),
"blockstampTime": next([b.medianTime for b in self.forge.blocks
if b.number == tx.blockstamp.number]),
"signatures": tx.signatures
}
for tx in user_identity.tx_received
],
"sending": [],
"receiving": [],
"pending": []
}
}, 200
def peer_doc(self):
peer = Peer(2, self.forge.currency, self.forge.key.pubkey, BlockUID.empty(),
[BMAEndpoint(None, "127.0.0.1", None, self.http.port)], None)
peer.sign([self.forge.key])
return peer