Skip to content
Snippets Groups Projects
Select Git revision
  • a680805e5cbd0c17eb53a6f83931069546fdfe49
  • dev default protected
  • vainamoinen197-transactiondocument-replace-vec-fields-by-smallvec-2
  • dvermd/200-keypairs-dewif
  • elois/wot
  • jawaka/155-dbex-add-dump-fork-tree-command
  • elois/195-bcdbwriteop
  • elois/deps-crypto
  • elois/gva-monetary-mass
  • elois/191-sled
  • elois/195
  • ji_emme/gva-humantimefield
  • 184-gva-rename-commontime-field-to-blockchaintime
  • ji_emme/182-gva-implement-block-meta-data
  • ji_emme/rml14
  • hugo/151-ws2pv2-sync
  • ji_emme/181-gva-implement-identity-request
  • ji_emme/89-implement-client-api-gva-graphql-verification-api
  • logo
  • test-juniper-from-schema
  • elois/exemple-gva-global-context
  • v0.2.0-a4 protected
  • v0.2.0-a2 protected
  • v0.2.0-a protected
  • v0.1.1-a1 protected
  • documents/v0.10.0-b1 protected
  • crypto/v0.4.0-b1 protected
  • crypto/v0.3.0-b3 protected
  • crypto/v0.3.0-b2 protected
  • crypto/v0.3.0-b1 protected
  • wot/v0.8.0-a0.9 protected
  • wot/v0.8.0-a0.8 protected
  • 0.1.0-a0.1 protected
  • v0.0.1-a0.12 protected
  • v0.0.1-a0.11 protected
  • v0.0.1-a0.10 protected
  • v0.0.1-a0.9 protected
  • v0.0.1-a0.8 protected
  • v0.0.1-a0.7 protected
  • v0.0.1-a0.6 protected
  • v0.0.1-a0.5 protected
41 results

Cargo.toml

Blame
  • This project manages its dependencies using Cargo. Learn more
    node.py 19.19 KiB
    import attr
    from duniterpy.documents import Peer, BMAEndpoint, BlockUID, Identity, Certification, Transaction
    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,
                '/wot/requirements/{pubkey}': node.requirements,
                '/blockchain/parameters': node.parameters,
                '/blockchain/with/ud': node.with_ud,
                '/blockchain/memberships/{search}': node.memberships,
                '/tx/history/{search}': node.tx_history,
            }
            post_routes = {
                '/wot/add': node.add,
                '/wot/certify': node.certify,
                '/tx/process': node.process
            }
            for r, h in get_routes.items():
                node.http.add_route("GET", r, h)
            for r, h in post_routes.items():
                node.http.add_route("POST", r, h)
            srv, port, url = await node.http.create_server()
            print("Server started on {0}".format(url))
            return node
    
        async def add(self, request):
            data = await request.post()
            identity = Identity.from_signed_raw(data["identity"])
            self.forge.pool.append(identity)
            return {}, 200
    
        async def process(self, request):
            data = await request.post()
            transaction = Transaction.from_signed_raw(data["transaction"])
            self.forge.pool.append(transaction)
            return {}, 200
    
        async def certify(self, request):
            data = await request.post()
            certification = Certification.from_signed_raw(data["cert"])
            self.forge.pool.append(certification)
            return {}, 200
    
        async def requirements(self, request):
            pubkey = request.match_info['pubkey']
            try:
                user_identity = self.forge.user_identities[pubkey]
            except KeyError:
                try:
                    user_identity = next(i for i in self.forge.user_identities.values() if i.uid == pubkey)
                except StopIteration:
                    return {
                        'ucode': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
                        'message': "No member matching this pubkey or uid"
                    }, 404
            return {
                        "identities": [
                                {
                                  "pubkey": user_identity.pubkey,
                                  "uid": user_identity.uid,
                                  "meta": {
                                    "timestamp": str(user_identity.blockstamp),
                                  },
                                  "expired": user_identity.revoked,
                                  "outdistanced": not user_identity.member,
                                  "certifications": [
                                    {
                                      "from": c.from_identity.pubkey,
                                      "to": c.to_identity.pubkey,
                                      "expiresIn": max(self.forge.blocks[-1].mediantime - 31557600 - c.mediantime, 0)
                                    } for c in user_identity.certs_received
                                    ],
                                    "membershipPendingExpiresIn": 0,
                                    "membershipExpiresIn": max(self.forge.blocks[-1].mediantime - 15778800
                                                               - user_identity.memberships[-1].timestamp, 0)
                                },
                            ]
                        }, 200
    
        async 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(number),
                    "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
    
        async 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
    
        async 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 KeyError:
                return {
                          "currency": self.forge.currency,
                          "pubkey": pubkey,
                          "sources": []
                       }, 200
    
        async 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
    
        async 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
    
        async def with_ud(self, request):
            return {
                "result": {
                    "blocks": [b.number for b in self.forge.blocks if b.ud]
                }
            }, 200
    
        async 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 {
                        'ucode': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
                        'message': "No member matching this pubkey or uid"
                    }, 404
    
            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
    
        async 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 {
                        'ucode': errors.NO_MEMBER_MATCHING_PUB_OR_UID,
                        'message': "No member matching this pubkey or uid"
                    }, 404
    
            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
    
        async 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 {
                        'ucode': 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
    
        async 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,
                        "uids": [
                            {
                                "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
    
        async 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 {
                        "currency": self.forge.currency,
                        "pubkey": search,
                        "history": {
                            "sent": [],
                            "received": [],
                            "sending": [],
                            "receiving": [],
                            "pending": []
                        }
                    }, 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
    
        async def close(self):
            await self.http.close()