Beispiel #1
0
 def _finalizeTx(self, tx):
     if hasattr(self, "_privateKey"):
         # set publicKey manualy
         dict.__setitem__(tx, "senderPublicKey", self.publicKey)
         tx["nonce"] = self.nonce + 1
         tx["senderId"] = self.address
         if tx["type"] not in [0, 8]:
             tx["recipientId"] = self.address
         tx.fee = self._fee
         tx.feeIncluded = self._fee_included
         tx["signature"] = crypto.getSignatureFromBytes(
             crypto.getBytes(tx), self._privateKey)
         if hasattr(self, "_secondPrivateKey"):
             tx["signSignature"] = \
                 crypto.getSignatureFromBytes(
                     crypto.getBytes(tx),
                     self._secondPrivateKey
                 )
         tx["id"] = crypto.getIdFromBytes(
             crypto.getBytes(tx, exclude_multi_sig=False))
     return tx
Beispiel #2
0
def append(network, *transactions):
    response = {}
    for tx in transactions:
        idx = transactions.index(tx) + 1
        try:
            if not isinstance(tx, dposlib.core.Transaction):
                tx = dposlib.core.Transaction(tx, ignore_bad_fields=True)
            signatures = tx.get("signatures", [])
            if len(signatures) == 0:
                response["errors"] = response.get("errors", []) + [
                    "transaction #%d rejected (one signature is mandatory)" %
                    idx
                ]
            elif tx.get("nonce", 1) <= tx._nonce:
                response["errors"] = response.get("errors", []) + [
                    "transaction #%d rejected (bad nonce)" % idx
                ]
            else:
                checks = []
                publicKeys = \
                    tx["asset"].get("multiSignature", {}).get(
                        "publicKeys", []
                    ) \
                    if tx["type"] == 4 else tx._multisignature.get(
                        "publicKeys", []
                    )
                serialized = crypto.getBytes(tx,
                                             exclude_sig=True,
                                             exclude_second_sig=True,
                                             exclude_multi_sig=True)
                for sig in signatures:
                    pk_idx, sig = int(sig[0:2], 16), sig[2:]
                    checks.append(
                        crypto.verifySignatureFromBytes(
                            serialized, publicKeys[pk_idx], sig))
                if False in checks:
                    response["errors"] = response.get("errors", []) + [
                        "transaction #%d rejected (bad signature)" % idx
                    ]
                else:
                    id_ = dump(network, tx)
                    response["success"] = response.get("success", []) + [
                        "transaction #%d successfully posted" % (idx)
                    ]
                    response["ids"] = response.get("ids", []) + [id_]
        except Exception as error:
            response["errors"] = response.get("errors", []) + [
                "transaction #%d rejected (%r)" % (idx, error)
            ]
    return json.dumps(response), 201
Beispiel #3
0
def identify(tx):
    """
    Identify a transaction.

    Args:
        tx (:class:`dict` or :class:`dposlib.blockchain.Transaction`):
            transaction to identify
    Returns:
        :class:`str`: transaction id used by registries
    """
    return crypto.getIdFromBytes(
        crypto.getBytes(tx,
                        exclude_sig=True,
                        exclude_multi_sig=True,
                        exclude_second_sig=True))
Beispiel #4
0
def remoteSignWithKey(network, ms_publicKey, txid, privateKey):
    publicKey = hexlify(
        secp256k1.PublicKey.from_seed(unhexlify(privateKey)).encode()
    )

    wallet = getWallet(network, ms_publicKey).get("data", {})
    if txid in wallet:
        options = {} if wallet[txid]["type"] == 4 else {
            "exclude_sig": True,
            "exclude_multi_sig": True,
            "exclude_second_sig": True
        }
        return putSignature(
            network, ms_publicKey, txid, publicKey,
            crypto.getSignatureFromBytes(
                crypto.getBytes(wallet[txid], **options),
                privateKey
            )
        )
    else:
        raise Exception("%s transaction not found" % txid)
Beispiel #5
0
def getSerial(network, ms_publicKey, txid):
    """
    ``GET /multisignature/{network}/{ms_publicKey}/{txid}/serial`` endpoint.
    Return specific pending transaction serial from a specific public key.
    """
    if network != getattr(rest.cfg, "network", False):
        rest.use(network)

    if flask.request.method != "GET":
        return json.dumps({
            "success": False,
            "API error": "GET request only allowed here"
        })

    tx = load(network, ms_publicKey, txid)
    if tx:
        return json.dumps({
            "success": True,
            "data": hexlify(crypto.getBytes(tx))
        }), 200
    else:
        return json.dumps({"success": False})
Beispiel #6
0
def putSignature(network, ms_publicKey):
    """
    ``PUT /multisignature/{network}/{ms_publicKey}/put`` endpoint. Add
    signature to a pending transaction::

        data = {
            "info": {
                "id": pending_transaction_id,
                "signature": signature,
                "publicKey": associated_public_key
            } [ + {
                "fee": optional_fee_value_to_use
            } ]
        }
    """
    if network != getattr(rest.cfg, "network", False):
        rest.use(network)

    if flask.request.method == "PUT":
        data = json.loads(flask.request.data)

        if "info" not in data:
            return json.dumps({"error": "no info"})

        txid = data["info"]["id"]
        tx = load(network, ms_publicKey, txid)

        if not tx:
            return json.dumps({
                "success": False,
                "API error": "transaction %s not found" % txid
            })

        tx = dposlib.core.Transaction(tx)
        publicKey = data["info"]["publicKey"]
        signature = data["info"]["signature"]
        publicKeys = \
            tx["asset"].get("multiSignature", {}).get("publicKeys", []) \
            if tx["type"] == 4 else tx._multisignature.get("publicKeys", [])

        if publicKey not in (publicKeys +
                             [tx._secondPublicKey, tx._publicKey]):
            return json.dumps({
                "success":
                False,
                "API error":
                "public key %s not allowed here" % publicKey
            })

        # sign type 4
        # signatures field is full
        if tx.type == 4 and len(tx.get("signatures", [])) == len(publicKeys):
            if publicKey == tx._publicKey:
                # and signature matches type 4 issuer's public key
                if crypto.verifySignatureFromBytes(crypto.getBytes(tx),
                                                   publicKey, signature):
                    tx.signature = signature
                    dump(network, tx)
                    if tx._secondPublicKey is None:
                        # if no need to signSign --> broadcast tx and return
                        # network response
                        return broadcast(network, tx)
                    else:
                        return json.dumps({
                            "success": True,
                            "message": "issuer signature added"
                        })
                else:
                    return json.dumps({
                        "success":
                        False,
                        "API error":
                        "signature does not match issuer key"
                    })
            # signSign
            elif publicKey == tx._secondPublicKey:
                # if tx already signed by issuer
                if "signature" in tx:
                    # and signature matches type 4 issuer 's second public key
                    if crypto.verifySignatureFromBytes(crypto.getBytes(tx),
                                                       publicKey, signature):
                        # signSign, broadcast and return network response
                        tx.signSignature = signature
                        return broadcast(network, tx)
                    else:
                        return json.dumps({
                            "success":
                            False,
                            "API error":
                            "signature does not match issuer "
                            "second key"
                        })
                else:
                    return json.dumps({
                        "success":
                        False,
                        "API error":
                        "transaction have to be signed first"
                    })

        # verify owner signature
        check = crypto.verifySignatureFromBytes(
            crypto.getBytes(tx,
                            exclude_sig=True,
                            exclude_multi_sig=True,
                            exclude_second_sig=True), publicKey, signature)
        # if signature matches
        if check and publicKey in publicKeys:
            index = publicKeys.index(publicKey)
            # set is used here to remove doubles
            tx["signatures"] = list(
                set(tx.get("signatures", []) + ["%02x" % index + signature]))
            if tx["type"] != 4 and \
               len(tx.get("signatures", [])) >= tx._multisignature["min"]:
                return broadcast(network, tx)
            else:
                dump(network, tx)
                return json.dumps({
                    "success": True,
                    "message": "signature added to transaction",
                }), 201
        else:
            return json.dumps({
                "success": False,
                "API error": "signature not accepted"
            })

    else:
        return json.dumps({
            "success": False,
            "API error": "PUT request only allowed here"
        })