def serialize(tx): buf = BytesIO() # deal with vendorField if "vendorFieldHex" in tx: vendorField = unhexlify(tx["vendorFieldHex"]) else: vendorField = tx["vendorField"].encode("utf-8") # common part pack("<BBBBI", buf, (255, Transaction.VERSION, rest.cfg.pubKeyHash, tx["type"], tx["timestamp"])) pack_bytes(buf, unhexlify(tx["senderPublicKey"])) pack("<QB", buf, (tx["fee"], len(vendorField))) pack_bytes(buf, vendorField) # custom part pack_bytes(buf, serializePayload(tx)) #signatures part pack_bytes(buf, unhexlify(tx["signature"])) if "signSignature" in tx: pack_bytes(buf, unhexlify(tx["signSignature"])) elif "secondSignature" in tx: pack_bytes(buf, unhexlify(tx["secondSignature"])) result = buf.getvalue() buf.close() return result
def _1_3(tx, buf): asset = tx.get("asset", {}) delegatePublicKeys = asset.get("votes", False) if delegatePublicKeys: pack("<B", buf, (len(delegatePublicKeys), )) for delegatePublicKey in delegatePublicKeys: delegatePublicKey = delegatePublicKey.replace("+", "01") \ .replace("-", "00") pack_bytes(buf, unhexlify(delegatePublicKey)) else: raise Exception("no up/down vote given")
def _1_2(tx, buf): asset = tx.get("asset", {}) username = asset.get("delegate", {}).get("username", False) if username: length = len(username) if 3 <= length <= 255: pack("<B", buf, (length, )) pack_bytes(buf, username.encode("utf-8")) else: raise Exception("bad username length [3-255]: %s" % username) else: raise Exception("no username defined")
def _9000_1(tx, buf): asset = tx["asset"].get("nftToken", {}) pack_bytes(buf, unhexlify(asset["collectionId"])) attributes = compactJson(asset["attributes"]) pack("<I", buf, (len(attributes), )) pack_bytes(buf, attributes.encode("utf-8")) recipientId = asset.get("recipientId", "") pack("<B", buf, (len(recipientId), )) if recipientId: pack_bytes(buf, recipientId.encode("utf-8"))
def serialize(tx, **options): """ Serialize transaction. Args: tx (dict or Transaction): transaction object. Returns: bytes: transaction serial representation. """ buf = BytesIO() vendorField = tx.get("vendorField", "").encode("utf-8")[:255] version = tx.get("version", 1) # common part pack("<BBB", buf, (0xff, version, cfg.pubkeyHash)) if version >= 2: pack("<IHQ", buf, ( tx.get("typeGroup", 1), tx["type"], tx["nonce"], )) else: pack("<BI", buf, ( tx["type"], tx["timestamp"], )) pack_bytes(buf, unhexlify(tx["senderPublicKey"])) pack("<QB", buf, (tx["fee"], len(vendorField))) pack_bytes(buf, vendorField) # custom part pack_bytes(buf, serde.serializePayload(tx)) # signatures part if not options.get("exclude_sig", False): pack_bytes(buf, unhexlify(tx.get("signature", ""))) if not options.get("exclude_second_sig", False): pack_bytes(buf, unhexlify(tx.get("signSignature", ""))) if "signatures" in tx and not options.get("exclude_multi_sig", False): if version == 1: pack("<B", buf, (0xff, )) pack_bytes(buf, b"".join([unhexlify(sig) for sig in tx["signatures"]])) # id part if "id" in tx: pack_bytes(buf, unhexlify(tx.get("id", ""))) result = buf.getvalue() buf.close() return result
def _9000_2(tx, buf): asset = tx["asset"].get("nftTransfer", {}) nftIds = asset["nftIds"][0:10] pack("<B", buf, (len(nftIds), )) for nftId in nftIds: pack_bytes(buf, unhexlify(nftId)) recipientId = \ str(tx["recipientId"]) \ if not isinstance(tx["recipientId"], bytes) \ else tx["recipientId"] recipientId = base58.b58decode_check(recipientId) pack_bytes(buf, recipientId)
def _1_4(tx, buf): asset = tx.get("asset", {}) multiSignature = asset.get("multiSignature", False) if multiSignature: pack( "<BB", buf, ( multiSignature["min"], len(multiSignature["publicKeys"]) ) ) pack_bytes( buf, b"".join( [unhexlify(sig) for sig in multiSignature["publicKeys"]] ) )
def _1_0(tx, buf): try: recipientId = \ str(tx["recipientId"]) \ if not isinstance(tx["recipientId"], bytes) \ else tx["recipientId"] recipientId = base58.b58decode_check(recipientId) except Exception: raise Exception("no recipientId defined") pack( "<QI", buf, ( int(tx.get("amount", 0)), int(tx.get("expiration", 0)) ) ) pack_bytes(buf, recipientId)
def _1_6(tx, buf): asset = tx.get("asset", {}) try: items = [ (p["amount"], base58.b58decode_check( str(p["recipientId"]) if not isinstance( p["recipientId"], bytes ) else p["recipientId"] )) for p in asset.get("payments", {}) ] except Exception: raise Exception("error in recipientId address list") pack("<H", buf, (len(items), )) for amount, address in items: pack("<Q", buf, (amount, )) pack_bytes(buf, address)
def _1_8(tx, buf): asset = tx.get("asset", {}) try: recipientId = \ str(tx["recipientId"]) \ if not isinstance(tx["recipientId"], bytes) \ else tx["recipientId"] recipientId = base58.b58decode_check(recipientId) except Exception: raise Exception("no recipientId defined") lock = asset.get("lock", False) expiration = lock.get("expiration", False) if not lock or not expiration: raise Exception("no lock nor expiration data found") pack("<Q", buf, (int(tx.get("amount", 0)),)) pack_bytes(buf, unhexlify(lock["secretHash"])) pack("<BI", buf, (int(expiration["type"]), int(expiration["value"]))) pack_bytes(buf, recipientId)
def _2_6(tx, buf): asset = tx.get("asset", {}) data = asset.get("data", {}) registrationId = unhexlify(asset.get("registrationId", "")) try: ipfs = data.get("ipfsData", "") ipfs = \ str(ipfs).encode("utf-8") if not isinstance(ipfs, bytes) \ else ipfs except Exception as e: raise Exception("bad ipfs hash\n%r" % e) try: name = data.get("name", "") name = \ str(name).encode("utf-8") if not isinstance(name, bytes) \ else name except Exception as e: raise Exception("bad entity name\n%r" % e) pack( "<BBBB", buf, ( int(asset.get("type", 0)), int(asset.get("subType", 0)), int(asset.get("action", 0)), len(registrationId) ) ) pack_bytes(buf, registrationId) pack("<B", buf, (len(name), )) pack_bytes(buf, name) pack("<B", buf, (len(ipfs), )) pack_bytes(buf, ipfs)
def getBytes(tx): buf = BytesIO() # write type and timestamp pack("<bi", buf, (tx["type"], tx["timestamp"])) # write senderPublicKey as bytes in buffer pack_bytes(buf, unhexlify(tx["senderPublicKey"])) # if there is a requesterPublicKey if "requesterPublicKey" in tx: pack_bytes(buf, unhexlify(tx["requesterPublicKey"])) # if there is a recipientId if "recipientId" in tx: pack(">Q", buf, (int(tx["recipientId"][:-len(cfg.marker)]),)) else: pack(">Q", buf, (0,)) # write amount pack("<Q", buf, (int(tx["amount"]),)) # if there is asset data if tx.get("asset", False): asset = tx["asset"] typ = tx["type"] if typ == 1 and "signature" in asset: pack_bytes(buf, unhexlify(asset["signature"]["publicKey"])) elif typ == 2 and "delegate" in asset: pack_bytes(buf, asset["delegate"]["username"].encode("utf-8")) elif typ == 3 and "votes" in asset: pack_bytes(buf, "".join(asset["votes"]).encode("utf-8")) else: pass # if there is a signature if tx.get("signature", False): pack_bytes(buf, unhexlify(tx["signature"])) # if there is a second signature if tx.get("signSignature", False): pack_bytes(buf, unhexlify(tx["signSignature"])) result = buf.getvalue() buf.close() return result
def serializePayload(tx): asset = tx.get("asset", {}) buf = BytesIO() _type = tx["type"] # transfer transaction if _type == 0: try: recipientId = str(tx["recipientId"]) if not isinstance( tx["recipientId"], bytes ) else \ tx["recipientId"] recipientId = base58.b58decode_check(recipientId) except Exception: raise Exception("no recipientId defined") pack("<QI", buf, ( int(tx.get("amount", 0)), int(tx.get("expiration", 0)), )) pack_bytes(buf, recipientId) # secondSignature registration elif _type == 1: if "signature" in asset: secondPublicKey = asset["signature"]["publicKey"] else: raise Exception("no secondSecret or secondPublicKey given") pack_bytes(buf, unhexlify(secondPublicKey)) # delegate registration elif _type == 2: username = asset.get("delegate", {}).get("username", False) if username: length = len(username) if 3 <= length <= 255: pack("<B", buf, (length, )) pack_bytes(buf, username.encode("utf-8")) else: raise Exception("bad username length [3-255]: %s" % username) else: raise Exception("no username defined") # vote elif _type == 3: delegatePublicKeys = asset.get("votes", False) if delegatePublicKeys: pack("<B", buf, (len(delegatePublicKeys), )) for delegatePublicKey in delegatePublicKeys: delegatePublicKey = delegatePublicKey.replace("+", "01")\ .replace("-", "00") pack_bytes(buf, unhexlify(delegatePublicKey)) else: raise Exception("no up/down vote given") # Multisignature registration elif _type == 4: multiSignature = asset.get("multiSignature", False) if multiSignature: pack("<BB", buf, (multiSignature["min"], len(multiSignature["publicKeys"]))) pack_bytes( buf, b"".join( [unhexlify(sig) for sig in multiSignature["publicKeys"]])) # IPFS elif _type == 5: try: ipfs = str(asset["ipfs"]) if not isinstance( asset["ipfs"], bytes) else asset["ipfs"] data = base58.b58decode(ipfs) except Exception as e: raise Exception("bad ipfs autentification\n%r" % e) pack_bytes(buf, data) # multipayment elif _type == 6: try: items = [(p["amount"], base58.b58decode_check( str(p["recipientId"]) if not isinstance( p["recipientId"], bytes) else p["recipientId"])) for p in asset.get("payments", {})] except Exception: raise Exception("error in recipientId address list") result = pack("<H", buf, (len(items), )) for amount, address in items: pack("<Q", buf, (amount, )) pack_bytes(buf, address) # delegate resignation elif _type == 7: pass # HTLC lock elif _type == 8: try: recipientId = str(tx["recipientId"]) if not isinstance( tx["recipientId"], bytes) else tx["recipientId"] recipientId = base58.b58decode_check(recipientId) except Exception: raise Exception("no recipientId defined") lock = asset.get("lock", False) expiration = lock.get("expiration", False) if not lock or not expiration: raise Exception("no lock nor expiration data found") pack("<Q", buf, (int(tx.get("amount", 0)), )) pack_bytes(buf, unhexlify(lock["secretHash"])) pack("<BI", buf, [int(expiration["type"]), int(expiration["value"])]) pack_bytes(buf, recipientId) # HTLC claim elif _type == 9: claim = asset.get("claim", False) if not claim: raise Exception("no claim data found") pack_bytes(buf, unhexlify(claim["lockTransactionId"])) pack_bytes(buf, claim["unlockSecret"].encode("utf-8")) # HTLC refund elif _type == 10: refund = asset.get("refund", False) if not refund: raise Exception("no refund data found") pack_bytes(buf, unhexlify(refund["lockTransactionId"])) else: raise Exception("Unknown transaction type %d" % tx["type"]) result = buf.getvalue() buf.close() return result
def serializePayload(tx): asset = tx.get("asset", {}) buf = BytesIO() # transfer transaction if tx["type"] == 0: try: recipientId = crypto.base58.b58decode_check(tx["recipientId"]) except: raise Exception("no recipientId defined") pack("<QI", buf, ( int(tx.get("amount", 0)), int(tx.get("expiration", 0)), )) pack_bytes(buf, recipientId) # secondSignature registration elif tx["type"] == 1: if "signature" in asset: secondPublicKey = asset["signature"]["publicKey"] else: raise Exception("no secondSecret or secondPublicKey given") pack_bytes(buf, unhexlify(secondPublicKey)) # delegate registration elif tx["type"] == 2: username = asset.get("delegate", {}).get("username", False) if username: length = len(username) if 3 <= length <= 255: pack("<B", buf, (length, )) pack_bytes(buf, username.encode("utf-8")) else: raise Exception("bad username length [3-255]: %s" % username) else: raise Exception("no username defined") # vote elif tx["type"] == 3: delegatePublicKeys = asset.get("votes", False) if delegatePublicKeys: payload = pack("<B", buf, (len(delegatePublicKeys), )) for delegatePublicKey in delegatePublicKeys: delegatePublicKey = delegatePublicKey.replace("+", "01").replace( "-", "00") pack_bytes(buf, unhexlify(delegatePublicKey)) else: raise Exception("no up/down vote given") # IPFS elif tx["type"] == 5: dag = asset.get("ipfs", {}).get("dag", False) if dag: dag = unhexlify(dag) pack("<B", buf, (len(dag), )) pack_bytes(buf, dag) else: raise Exception("no IPFS DAG given") # timelock transaction elif tx["type"] == 6: try: recipientId = crypto.base58.b58decode_check(tx["recipientId"]) except: raise Exception("no recipientId defined") pack("<QBI", buf, ( int(tx.get("amount", 0)), int(tx.get("timelockType", 0)), int(tx.get("timelock", 0)), )) pack_bytes(buf, recipientId) # multipayment elif tx["type"] == 7: try: items = [(p["amount"], crypto.base58.b58decode_check(p["recipientId"])) for p in asset.get("payments", {})] except: raise Exception("error in recipientId address list") result = pack(buf, "<H", (len(items), )) for amount, address in items: pack("<Q", buf, (amount, )) pack_bytes(buf, address) # delegate resignation elif tx["type"] == 8: pass else: raise Exception("Unknown transaction type %d" % tx["type"]) result = buf.getvalue() buf.close() return result
def getBytes(tx, **options): """ Hash transaction. Args: tx (dict or Transaction): transaction object. **Options**: * `exclude_sig` *bool* - exclude signature during tx serialization. Defalut to False. * `exclude_multi_sig` *bool* - exclude signatures during tx serialization. Defalut to False. * `exclude_second_sig` *bool* - exclude second signatures during tx serialization. Defalut to False. Returns: bytes: transaction serial. """ if tx.get("version", 0x01) >= 0x02: return serialize(tx, **options) buf = BytesIO() # write type and timestamp pack("<BI", buf, (tx["type"], int(tx["timestamp"]))) # write senderPublicKey as bytes in buffer if "senderPublicKey" in tx: pack_bytes(buf, unhexlify(tx["senderPublicKey"])) # if there is a requesterPublicKey if "requesterPublicKey" in tx: pack_bytes(buf, unhexlify(tx["requesterPublicKey"])) # if there is a recipientId or tx not a second secret nor a multi # singature registration if tx.get("recipientId", False) and tx["type"] not in [1, 4]: recipientId = tx["recipientId"] recipientId = base58.b58decode_check( str(recipientId ) if not isinstance(recipientId, bytes) else recipientId) else: recipientId = b"\x00" * 21 pack_bytes(buf, recipientId) # deal with vendorField values if "vendorFieldHex" in tx: vendorField = unhexlify(tx["vendorFieldHex"]) else: value = tx.get("vendorField", b"") if not isinstance(value, bytes): value = value.encode("utf-8") vendorField = value vendorField = vendorField[:64].ljust(64, b"\x00") pack_bytes(buf, vendorField) # write amount and fee value pack("<QQ", buf, (tx.get("amount", 0), tx["fee"])) # if there is asset data if tx.get("asset", False): asset, typ = tx["asset"], tx["type"] if typ == 1 and "signature" in asset: pack_bytes(buf, unhexlify(asset["signature"]["publicKey"])) elif typ == 2 and "delegate" in asset: pack_bytes(buf, asset["delegate"]["username"].encode("utf-8")) elif typ == 3 and "votes" in asset: pack_bytes(buf, "".join(asset["votes"]).encode("utf-8")) else: raise Exception("transaction type %s not implemented" % typ) # if there is a signature if "signature" in tx and not options.get("exclude_sig", False): pack_bytes(buf, unhexlify(tx["signature"])) # if there is a second signature if not options.get("exclude_second_sig", False): if tx.get("signSignature", False): pack_bytes(buf, unhexlify(tx["signSignature"])) elif tx.get("secondSignature", False): pack_bytes(buf, unhexlify(tx["secondSignature"])) result = buf.getvalue() buf.close() return result
def getBytes(tx, ark_v2=False): """ Hash transaction object into bytes data. Argument: tx (dict) -- transaction object Return bytes sequence """ buf = BytesIO() # write type and timestamp pack("<BI", buf, (tx["type"], int(tx["timestamp"]))) # write senderPublicKey as bytes in buffer if "senderPublicKey" in tx: pack_bytes(buf, unhexlify(tx["senderPublicKey"])) # if there is a requesterPublicKey if "requesterPublicKey" in tx: pack_bytes(buf, unhexlify(tx["requesterPublicKey"])) # if there is a recipientId or tx not a second secret nor a multi singature registration if tx.get("recipientId", False) and tx["type"] not in [1, 4]: recipientId = tx["recipientId"] recipientId = base58.b58decode_check( str(recipientId) if not isinstance(recipientId, bytes) else \ recipientId ) else: recipientId = b"\x00" * 21 pack_bytes(buf, recipientId) # if there is a vendorField if tx.get("vendorField", False): vendorField = tx["vendorField"][:64].ljust(64, "\x00") else: vendorField = "\x00" * 64 pack_bytes(buf, vendorField.encode("utf-8")) # write amount and fee value pack("<QQ", buf, (tx.get("amount", 0), tx["fee"])) # if there is asset data if tx.get("asset", False): asset, typ = tx["asset"], tx["type"] if typ == 1 and "signature" in asset: pack_bytes(buf, unhexlify(asset["signature"]["publicKey"])) elif typ == 2 and "delegate" in asset: pack_bytes(buf, asset["delegate"]["username"].encode("utf-8")) elif typ == 3 and "votes" in asset: pack_bytes(buf, "".join(asset["votes"]).encode("utf-8")) # elif typ == 4: # multisignature = asset.get("multisignature", {}) # pack("<bb", buf, (multisignature["min"], multisignature["lifetime"])) # pack_bytes(buf, "".join(multisignature["keysgroup"]).encode("utf-8")) else: raise Exception("transaction type %s not implemented" % typ) # if there is a signature if tx.get("signature", False): pack_bytes(buf, unhexlify(tx["signature"])) # if there is a second signature if tx.get("signSignature", False): pack_bytes(buf, unhexlify(tx["signSignature"])) result = buf.getvalue() buf.close() return result
def _9000_0(tx, buf): asset = tx["asset"].get("nftCollection", {}) name = asset["name"] if 5 <= len(name) <= 40: pack("<B", buf, (len(name), )) pack_bytes(buf, name.encode("utf-8")) else: raise Exception("bad namelength [5-80]: %s" % name) description = asset["description"] if 5 <= len(description) <= 80: pack("<B", buf, (len(description), )) pack_bytes(buf, description.encode("utf-8")) else: raise Exception("bad description length [5-80]: %s" % description) pack("<I", buf, (max(1, asset["maximumSupply"]), )) jsonSchema = compactJson(asset["jsonSchema"]) pack("<I", buf, (len(jsonSchema), )) pack_bytes(buf, jsonSchema.encode("utf-8")) allowedIssuers = asset.get("allowedIssuers", [])[:10] pack("<I", buf, (len(allowedIssuers), )) for allowedIssuer in allowedIssuers: pack_bytes(buf, unhexlify(allowedIssuer)) metadata = compactJson(asset.get("metadata", {})) pack("<I", buf, (len(metadata), )) pack_bytes(buf, metadata.encode("utf-8"))