def serialize(self, include_signature=True): milestone = config.get_milestone(self.height - 1) if milestone["block"]["idFullSha256"]: if len(self.previous_block) != 64: raise Exception( "Previous block shoud be SHA256, but found a non SHA256 block id" ) self.previous_block_hex = self.previous_block.encode("utf-8") else: self.previous_block_hex = Block.to_bytes_hex(self.previous_block) bytes_data = bytes() bytes_data += write_bit32(self.version) bytes_data += write_bit32(self.timestamp) bytes_data += write_bit32(self.height) bytes_data += unhexlify(self.previous_block_hex) bytes_data += write_bit32(self.number_of_transactions) bytes_data += write_bit64(int(self.total_amount)) bytes_data += write_bit64(int(self.total_fee)) bytes_data += write_bit64(int(self.reward)) bytes_data += write_bit32(self.payload_length) bytes_data += unhexlify(self.payload_hash.encode("utf-8")) bytes_data += unhexlify(self.generator_public_key) if include_signature and self.block_signature: bytes_data += unhexlify(self.block_signature.encode("utf-8")) return hexlify(bytes_data)
def get_bytes(self, skip_signature=False, skip_second_signature=False): """ Serializes the given transaction prior to AIP11 (legacy). """ # TODO: rename to to_bytes which makes more sense than get_bytes if self.version and self.version != 1: raise Exception( "Invalid transaction version") # TODO: better exception bytes_data = bytes() bytes_data += write_bit8(self.type) bytes_data += write_bit32(self.timestamp) bytes_data += write_high(self.sender_public_key) # Apply a fix for broken type 1 (second signature) and 4 (multi signature) # transactions, which were erroneously calculated with a recipient id, # also apply a fix for all other broken transactions is_broken_type = self.type in [ TRANSACTION_TYPE_SECOND_SIGNATURE, TRANSACTION_TYPE_MULTI_SIGNATURE, ] if not self.recipient_id or (is_transaction_exception(self.id) or is_broken_type): bytes_data += pack("21x") else: bytes_data += b58decode_check(self.recipient_id) if self.vendor_field: encoded_vendor_field = self.vendor_field.encode("utf-8") bytes_data += encoded_vendor_field num_of_zeroes = 64 - len(encoded_vendor_field) if num_of_zeroes > 0: bytes_data += pack("{}x".format(num_of_zeroes)) else: bytes_data += pack("64x") bytes_data += write_bit64(self.amount) bytes_data += write_bit64(self.fee) if self.type == TRANSACTION_TYPE_SECOND_SIGNATURE: public_key = self.asset["signature"]["publicKey"] bytes_data += unhexlify(public_key) elif self.type == TRANSACTION_TYPE_DELEGATE_REGISTRATION: bytes_data += self.asset["delegate"]["username"].encode() elif self.type == TRANSACTION_TYPE_VOTE: bytes_data += "".join(self.asset["votes"]).encode() elif self.type == TRANSACTION_TYPE_MULTI_SIGNATURE: bytes_data += write_bit8(self.asset["multisignature"]["min"]) bytes_data += write_bit8(self.asset["multisignature"]["lifetime"]) bytes_data += "".join( self.asset["multisignature"]["keysgroup"]).encode() if not skip_signature and self.signature: bytes_data += write_high(self.signature) if not skip_second_signature and self.sign_signature: bytes_data += write_high(self.sign_signature) return bytes_data
def serialize(self, include_signature=True): # TODO: make this a serializer that correctly converts input and checks that it's correct # on init self.previous_block_hex = Block.to_bytes_hex(int(self.previous_block)) bytes_data = bytes() bytes_data += write_bit32(self.version) bytes_data += write_bit32(self.timestamp) bytes_data += write_bit32(self.height) bytes_data += unhexlify(self.previous_block_hex) bytes_data += write_bit32(self.number_of_transactions) bytes_data += write_bit64(int(self.total_amount)) bytes_data += write_bit64(int(self.total_fee)) bytes_data += write_bit64(int(self.reward)) bytes_data += write_bit32(self.payload_length) bytes_data += unhexlify(self.payload_hash) bytes_data += unhexlify(self.generator_public_key) if include_signature and self.block_signature: bytes_data += unhexlify(self.block_signature) return hexlify(bytes_data).decode()
def serialize_full(self): if not self.transactions: self.transactions = [] if not self.number_of_transactions: self.number_of_transactions = len(self.transactions) bytes_data = unhexlify(self.serialize()) all_transaction_bytes = bytes() for transaction in self.transactions: serialized_transaction = unhexlify(transaction.serialize()) bytes_data += write_bit32(len(serialized_transaction)) all_transaction_bytes += serialized_transaction bytes_data += all_transaction_bytes return hexlify(bytes_data)
def serialize_full(self): # TODO: try to make these as default values instead of checking for it here if not self.transactions: self.transactions = [] if not self.number_of_transactions: self.number_of_transactions = len(self.transactions) bytes_data = unhexlify(self.serialize()) all_transaction_bytes = bytes() for transaction in self.transactions: serialized_transaction = Transaction(transaction).serialize() bytes_data += write_bit32(len(unhexlify(serialized_transaction))) all_transaction_bytes += unhexlify(serialized_transaction) bytes_data += all_transaction_bytes return hexlify(bytes_data).decode()
def serialize(self): """Serialize Transaction """ bytes_data = bytes() # bytes() or bytes(512)? bytes_data += write_bit8( 0xFF) # fill, to distinguish between v1 and v2 bytes_data += write_bit8(self.version or 0x01) bytes_data += write_bit8(self.network or config.network["pubKeyHash"]) bytes_data += write_bit8(self.type) bytes_data += write_bit32(self.timestamp) bytes_data += write_high(self.sender_public_key.encode("utf-8")) bytes_data += write_bit64(self.fee) # TODO: test this thorougly as it might be completely wrong bytes_data += self._serialize_vendor_field() bytes_data += self._serialize_type() bytes_data += self._serialize_signatures() return hexlify(bytes_data)
def _serialize_type(self): """Serialize transaction specific data (eg. delegate registration) """ bytes_data = bytes() if self.type == TRANSACTION_TYPE_TRANSFER: bytes_data += write_bit64(self.amount) bytes_data += write_bit32(self.expiration or 0) bytes_data += write_high( hexlify(b58decode_check(self.recipient_id))) elif self.type == TRANSACTION_TYPE_SECOND_SIGNATURE: bytes_data += unhexlify( self.asset['signature']['publicKey'].encode('utf-8')) elif self.type == TRANSACTION_TYPE_DELEGATE_REGISTRATION: delegate_bytes = hexlify( self.asset['delegate']['username'].encode('utf-8')) bytes_data += write_bit8(len(delegate_bytes)) bytes_data += unhexlify(delegate_bytes) elif self.type == TRANSACTION_TYPE_VOTE: vote_bytes = [] for vote in self.asset['votes']: if vote.startswith('+'): vote_bytes.append('01{}'.format(vote[1:])) else: vote_bytes.append('00{}'.format(vote[1:])) bytes_data += write_bit8(len(self.asset['votes'])) bytes_data += unhexlify(''.join(vote_bytes)) elif self.type == TRANSACTION_TYPE_MULTI_SIGNATURE: keysgroup = [] if self.version is None or self.version == 1: for key in self.asset['multisignature']['keysgroup']: keysgroup.append(key[1:] if key.startswith('+') else key) else: keysgroup = self.asset['multisignature']['keysgroup'] bytes_data += write_bit8(self.asset['multisignature']['min']) bytes_data += write_bit8( len(self.asset['multisignature']['keysgroup'])) bytes_data += write_bit8(self.asset['multisignature']['lifetime']) bytes_data += unhexlify(''.join(keysgroup)) elif self.type == TRANSACTION_TYPE_IPFS: bytes_data += write_bit8(len(self.asset['ipfs']['dag']) // 2) bytes_data += unhexlify(self.asset['ipfs']['dag']) elif self.type == TRANSACTION_TYPE_TIMELOCK_TRANSFER: bytes_data += write_bit64(self.amount) bytes_data += write_bit8(self.timelock_type) bytes_data += write_bit64(self.timelock) bytes_data += hexlify(b58decode_check(self.recipientId)) elif self.type == TRANSACTION_TYPE_MULTI_PAYMENT: bytes_data += write_bit32(len(self.asset['payments'])) for payment in self.asset['payments']: bytes_data += write_bit64(payment['amount']) bytes_data += hexlify(b58decode_check(payment['recipientId'])) elif self.type == TRANSACTION_TYPE_DELEGATE_RESIGNATION: pass else: raise Exception( 'Transaction type is invalid') # TODO: better exception return bytes_data
def _serialize_type(self): """Serialize transaction specific data (eg. delegate registration) """ bytes_data = bytes() if self.type == TRANSACTION_TYPE_TRANSFER: bytes_data += write_bit64(self.amount) bytes_data += write_bit32(self.expiration or 0) bytes_data += write_high( hexlify(b58decode_check(self.recipient_id))) elif self.type == TRANSACTION_TYPE_SECOND_SIGNATURE: bytes_data += unhexlify( self.asset["signature"]["publicKey"].encode("utf-8")) elif self.type == TRANSACTION_TYPE_DELEGATE_REGISTRATION: delegate_bytes = hexlify( self.asset["delegate"]["username"].encode("utf-8")) bytes_data += write_bit8(len(delegate_bytes)) bytes_data += unhexlify(delegate_bytes) elif self.type == TRANSACTION_TYPE_VOTE: vote_bytes = [] for vote in self.asset["votes"]: if vote.startswith("+"): vote_bytes.append("01{}".format(vote[1:])) else: vote_bytes.append("00{}".format(vote[1:])) bytes_data += write_bit8(len(self.asset["votes"])) bytes_data += unhexlify("".join(vote_bytes)) elif self.type == TRANSACTION_TYPE_MULTI_SIGNATURE: keysgroup = [] if self.version is None or self.version == 1: for key in self.asset["multisignature"]["keysgroup"]: keysgroup.append(key[1:] if key.startswith("+") else key) else: keysgroup = self.asset["multisignature"]["keysgroup"] bytes_data += write_bit8(self.asset["multisignature"]["min"]) bytes_data += write_bit8( len(self.asset["multisignature"]["keysgroup"])) bytes_data += write_bit8(self.asset["multisignature"]["lifetime"]) bytes_data += unhexlify("".join(keysgroup).encode("utf-8")) elif self.type == TRANSACTION_TYPE_IPFS: bytes_data += write_bit8(len(self.asset["ipfs"]["dag"]) // 2) bytes_data += unhexlify(self.asset["ipfs"]["dag"]) elif self.type == TRANSACTION_TYPE_TIMELOCK_TRANSFER: bytes_data += write_bit64(self.amount) bytes_data += write_bit8(self.timelock_type) bytes_data += write_bit64(self.timelock) bytes_data += b58decode_check(self.recipient_id) elif self.type == TRANSACTION_TYPE_MULTI_PAYMENT: bytes_data += write_bit32(len(self.asset["payments"])) for payment in self.asset["payments"]: bytes_data += write_bit64(payment["amount"]) bytes_data += b58decode_check(payment["recipientId"]) elif self.type == TRANSACTION_TYPE_DELEGATE_RESIGNATION: pass else: raise Exception( "Transaction type is invalid") # TODO: better exception return bytes_data