def AddSignature(self, contract, pubkey, signature): if contract.Type == ContractType.MultiSigContract: item = self.CreateItem(contract) if item is None: return False for p in item.ContractParameters: if p.Value is not None: return False if item.Signatures is None: item.Signatures = {} elif pubkey.encode_point(True) in item.Signatures: return False points = [] temp = binascii.unhexlify(contract.Script) ms = MemoryStream(binascii.unhexlify(contract.Script)) reader = BinaryReader(ms) numr = reader.ReadUInt8() while reader.ReadUInt8() == 33: points.append(binascii.hexlify(reader.ReadBytes(33))) ms.close() if pubkey.encode_point(True) not in points: return False item.Signatures[pubkey.encode_point(True).decode()] = binascii.hexlify(signature) if len(item.Signatures) == len(contract.ParameterList): i = 0 points.sort(reverse=True) for k in points: if k.decode() in item.Signatures: if self.Add(contract, i, item.Signatures[k.decode()]) is None: raise Exception("Invalid operation") i += 1 item.Signatures = None return True else: index = -1 if contract.ParameterList == '00': contract.ParameterList = b'\x00' length = len(contract.ParameterList) for i in range(0, length): if ContractParameterType(contract.ParameterList[i]) == ContractParameterType.Signature: if index >= 0: raise Exception("Signature must be first") else: index = i return self.Add(contract, index, signature)
def test_yet_another_tx(self): ms = MemoryStream(binascii.unhexlify(self.yatx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.yatx) self.assertEqual(tx.Hash.ToBytes(), self.yatx_id)
def test_contract_tx_again(self): ms = MemoryStream(binascii.unhexlify(self.cr)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.cr) self.assertEqual(tx.Hash.ToBytes(), self.crid)
def ToJson(self): jsn = {} jsn['type'] = 'Neo.Core.ContractTransaction' # Verifiable.GetType().FullName ms = MemoryStream() w = BinaryWriter(ms) self.Verifiable.SerializeUnsigned(w) ms.flush() jsn['hex'] = ms.ToArray().decode() jsn['items'] = {} for key, value in self.ContextItems.items(): if type(key) == str: shkey = "0x{}".format(key) else: shkey = "0x{}".format(key.decode()) jsn['items'][shkey] = value.ToJson() return jsn
def test_miner_tx(self): ms = MemoryStream(binascii.unhexlify(self.mr)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.Nonce, self.mrn) self.assertEqual(tx.ToArray(), self.mr) self.assertEqual(tx.Hash.ToBytes(), self.mrh)
def test_invocation_transaction(self): ms = MemoryStream(binascii.unhexlify(self.ir)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.ir) self.assertEqual(tx.Hash.ToBytes(), self.ir_id)
class ScriptBuilder(object): """docstring for ScriptBuilder""" def __init__(self): super(ScriptBuilder, self).__init__() self.ms = MemoryStream() # MemoryStream def add(self, op): if isinstance(op, int): self.ms.write(bytes([op])) else: self.ms.write(op) return def push(self, data): if data == None: return if isinstance(data,int): if data == -1: return self.add(PUSHM1) elif data == 0: return self.add(PUSH0) elif data > 0 and data <= 16: return self.add(int.from_bytes(PUSH1,'big') -1 + data) else: return self.push(bytes(data)) else: buf = binascii.unhexlify(data) if len(buf) <= int.from_bytes( PUSHBYTES75, 'big'): self.add(len(buf)) self.add(buf) elif len(buf) < 0x100: self.add(PUSH1) self.add(len(buf)) self.add(buf) elif len(buf) < 0x10000: self.add(PUSH2) self.add(len(buf) & 0xff) self.add(len(buf) >> 8) self.add(buf) elif len(buf) < 0x100000000: self.add(PUSH4) self.add(len(buf) & 0xff) self.add((len(buf) >> 8) & 0xff) self.add((len(buf) >> 16) & 0xff) self.add(len(buf) >> 24) self.add(buf) return def ToArray(self): self.ms.flush() retval = self.ms.ToArray() self.ms.Cleanup() self.ms = None return retval
def test_enrollment_tx(self): ms = MemoryStream(binascii.unhexlify(self.eraw)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.eraw) self.assertEqual(tx.Hash.ToBytes(), self.eid)
def test_pub_two(self): ms = MemoryStream(binascii.unhexlify(self.p2)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.p2) self.assertEqual(tx.Hash.ToBytes(), self.p2id)
def test_GetScriptHashesForVerifying_neo_gas(self): # test a raw tx using neo ms = MemoryStream(binascii.unhexlify(self.ntx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx.raw_tx = True res = tx.GetScriptHashesForVerifying() self.assertTrue(type(res), list) # test a raw tx using gas ms = MemoryStream(binascii.unhexlify(self.gtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx.raw_tx = True res = tx.GetScriptHashesForVerifying() self.assertTrue(type(res), list)
def test_enrollment_tx(self): ms = MemoryStream(binascii.unhexlify(self.eraw)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.eraw) self.assertEqual(tx.Hash.ToBytes(), self.eid) self.assertEqual( Fixed8.FromDecimal(settings.ALL_FEES['EnrollmentTransaction']), tx.SystemFee())
def test_GetScriptHashesForVerifying_invalid_operation(self): # test a normal tx with a bad assetId ms = MemoryStream(binascii.unhexlify(self.rtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) with self.assertRaises(Exception) as e: tx.GetScriptHashesForVerifying() self.assertTrue("Invalid operation" in str(e.exception)) # test a raw tx with a bad assetId ms = MemoryStream(binascii.unhexlify(self.rtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx.raw_tx = True with self.assertRaises(Exception) as e: tx.GetScriptHashesForVerifying() self.assertTrue("Invalid operation" in str(e.exception))
def test_pub_two(self): ms = MemoryStream(binascii.unhexlify(self.p2)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.p2) self.assertEqual(tx.Hash.ToBytes(), self.p2id) json = tx.ToJson() self.assertEqual(json['size'], 402) self.assertEqual(json['type'], 'PublishTransaction')
def test_contract_tx_deserialize(self): ms = MemoryStream(binascii.unhexlify(self.ctx_raw)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.ctx_raw) self.assertEqual(tx.Hash.ToBytes(), self.ctx_id) json = tx.ToJson() self.assertEqual(json['size'], 605) self.assertEqual(json['type'], 'ContractTransaction')
def FromTrimmedData(bytes, index, transaction_method): block = Block() ms = MemoryStream() reader = BinaryReader(ms) block.DeserializeUnsigned(reader) reader.ReadByte() block.Script = reader.ReadSerializableArray('neo.Core.Witness.Witness') block.Transactions = [] for i in range(0, reader.ReadVarInt()): tx = Transaction.DeserializeFrom(reader) block.Transactions.append(tx) return block
def test_register_tx(self): ms = MemoryStream(binascii.unhexlify(self.rr)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(self.rrid, tx.Hash.ToBytes()) json = tx.ToJson() asset = json['asset'] self.assertEqual(asset['admin'], 'ARFe4mTKRTETerRoMsyzBXoPt2EKBvBXFX') self.assertEqual(asset['name'], '[{"lang":"zh-CN","name":"TestCoin"}]') self.assertEqual(asset['precision'], 8)
def FromTrimmedData(data, index): header = Header() ms = MemoryStream(data) reader = BinaryReader(ms) header.DeserializeUnsigned(reader) reader.ReadByte() witness = Witness() witness.Deserialize(reader) header.Script = witness return header
def test_verify_claim_tx_high_priority(self): ms = MemoryStream(binascii.unhexlify(self.cltx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.cltx) self.assertEqual(tx.Hash.ToBytes(), self.cltx_id) snapshot = GetBlockchain()._db.createSnapshot() with patch("neo.Core.TX.Transaction.Transaction.Size", return_value=(settings.MAX_FREE_TX_SIZE + 1)): with patch('neo.SmartContract.Helper.Helper.VerifyWitnesses', return_value=True): # we are not testing VerifyScripts with patch('neo.Core.Blockchain.Blockchain.CalculateBonusIgnoreClaimed', return_value=Fixed8.FromDecimal(0.30551243)): res = tx.Verify(snapshot, [tx]) self.assertTrue(res) tx_size = tx.Size() self.assertGreater(tx_size, settings.MAX_FREE_TX_SIZE)
def test_GetScriptHashesForVerifying_DutyFlag(self): # test a raw tx ms = MemoryStream(binascii.unhexlify(self.rtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx.raw_tx = True # create the mocked asset mock_asset = AssetState() mock_asset.AssetType = 0x80 snapshot = GetBlockchain()._db.createSnapshot() with patch("neo.Core.Helper.Helper.StaticAssetState", return_value=mock_asset): res = tx.GetScriptHashesForVerifying(snapshot) self.assertTrue(type(res), list) self.assertEqual(res[0], Helper.AddrStrToScriptHash("AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3"))
def test_verify_exceeds_max_tx_size(self): ms = MemoryStream(binascii.unhexlify(self.vvtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) tx._network_fee = Fixed8.FromDecimal(0.001) self.assertEqual(tx.ToArray(), self.vvtx) self.assertEqual(tx.Hash.ToBytes(), self.vvtx_id) snapshot = GetBlockchain()._db.createSnapshot() with patch("neo.Core.TX.Transaction.Transaction.Size", return_value=(Transaction.MAX_TX_SIZE + 1)): res = tx.Verify(snapshot, [tx]) self.assertFalse(res) tx_size = tx.Size() self.assertGreater(tx_size, Transaction.MAX_TX_SIZE)
def ImportFromArray(self, raw_tx): """ Import a raw transaction from an array. Args: raw_tx: (bytes) the raw transaction array """ if not isinstance(raw_tx, bytes): raise TypeError('Please input a byte array.') try: raw_tx = binascii.unhexlify(raw_tx) ms = MemoryStream(raw_tx) reader = BinaryReader(ms) self.DeserializeFrom(reader) except Exception as e: raise FormatError( f'Unable to import raw transaction.\nError output: {e}')
def test_claim_tx(self): ms = MemoryStream(binascii.unhexlify(self.cltx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.cltx) self.assertEqual(tx.Hash.ToBytes(), self.cltx_id) json = tx.ToJson() self.assertEqual(json['size'], 577) self.assertEqual(json['type'], "ClaimTransaction") self.assertEqual(json['version'], 0) self.assertEqual(len(json['attributes']), 0) self.assertEqual(len(json['vout']), 1) self.assertEqual(len(json['vin']), 0) self.assertEqual(json['sys_fee'], "0") self.assertEqual(json['net_fee'], "0") self.assertEqual(len(json['claims']), 12)
def test_publish_tx_deserialize(self): ms = MemoryStream(binascii.unhexlify(self.pb_raw)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.pb_raw) self.assertEqual(tx.Hash.ToBytes(), self.pb_hash) json = tx.ToJson() contract = json['contract'] self.assertEqual(contract['author'], 'Erik Zhang') self.assertEqual(contract['description'], 'Lock your assets until a timestamp.') self.assertEqual(contract['code']['hash'], 'ffbd1a7ad1e2348b6b3822426f364bfb4bcce3b9') self.assertEqual(contract['code']['returntype'], 1) self.assertEqual(contract['code']['parameters'], '020500')
def DeserializeFromAsyncSocket(socket, cancellation_token): buffer = bytearray(24) try: socket.recv_into(buffer, 24) ms = MemoryStream(buffer) reader = BinaryReader(ms) message = Message() message.Magic = reader.ReadUInt32() message.Command = reader.ReadFixedString(12).decode('utf-8') length = reader.ReadUInt32() if length > Message.PayloadMaxSizeInt: raise Exception("format too big") message.Checksum = reader.ReadUInt32() message.Payload = bytearray(length) if length > 0: message.Payload = Message.FillBufferAsyncStream( socket, length, None) checksum = Message.GetChecksum(message.Payload) if checksum != message.Checksum: print("Message command :%s " % message.Command) print("Checksum mismatch: %s " % message.Checksum) print("message payload: %s " % message.Payload) raise Exception("invalid checksum") return message except Exception as e: print("could not receive buffer from socket: %s " % e)
def test_verify_exceeds_free_tx_size_less_low_priority_threshhold(self): ms = MemoryStream(binascii.unhexlify(self.vtx)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.vtx) self.assertEqual(tx.Hash.ToBytes(), self.vtx_id) snapshot = GetBlockchain()._db.createSnapshot() res = tx.Verify(snapshot, [tx]) self.assertFalse(res) tx_size = tx.Size() self.assertGreater(tx_size, settings.MAX_FREE_TX_SIZE) req_fee = Fixed8.FromDecimal(settings.FEE_PER_EXTRA_BYTE * (tx_size - settings.MAX_FREE_TX_SIZE)) self.assertLess(req_fee, settings.LOW_PRIORITY_THRESHOLD) n_fee = tx.NetworkFee() self.assertEqual(n_fee.ToString(), '0') self.assertLess(n_fee, req_fee)
def test_publish_tx_deserialize(self): ms = MemoryStream(binascii.unhexlify(self.pb_raw)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(tx.ToArray(), self.pb_raw) self.assertEqual(tx.Hash.ToBytes(), self.pb_hash) json = tx.ToJson() self.assertEqual(json['size'], 613) self.assertEqual(json['type'], 'PublishTransaction') contract = json['contract'] self.assertEqual(contract['author'], 'Erik Zhang') self.assertEqual(contract['description'], 'Lock your assets until a timestamp.') self.assertEqual(contract['code']['hash'], '0xffbd1a7ad1e2348b6b3822426f364bfb4bcce3b9') self.assertEqual(contract['code']['returntype'], "Boolean") self.assertEqual(contract['code']['parameters'], ['Integer', 'ByteArray', 'Signature']) self.assertEqual(Fixed8.FromDecimal(settings.ALL_FEES['PublishTransaction']), tx.SystemFee())
def test_issue_tx(self): ms = MemoryStream(binascii.unhexlify(self.ii)) reader = BinaryReader(ms) tx = Transaction.DeserializeFrom(reader) self.assertEqual(self.ii_id, tx.Hash.ToBytes()) json = tx.ToJson() self.assertEqual(json['size'], 69) self.assertEqual(json['type'], "IssueTransaction") self.assertEqual(json['version'], 0) self.assertEqual(len(json['attributes']), 0) jsn_vout = json['vout'][0] self.assertEqual(jsn_vout['asset'], "0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b") self.assertEqual(jsn_vout['value'], "100000000") self.assertEqual(jsn_vout['address'], "AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i") self.assertEqual(len(json['vin']), 0) self.assertEqual(json['sys_fee'], "0") self.assertEqual(json['net_fee'], "0") self.assertEqual(json['scripts'][0]['invocation'], "") self.assertEqual(json['scripts'][0]['verification'], "51")
def test_message_serialization(self): message = Message('version', payload=self.payload) self.assertEqual(message.Command, 'version') ms = MemoryStream() writer = BinaryWriter(ms) message.Serialize(writer) ms.flush() result = binascii.unhexlify(ms.ToArray()) ms = MemoryStream(result) reader = BinaryReader(ms) deserialized_message = Message() deserialized_message.Deserialize(reader) dm = deserialized_message self.assertEqual(dm.Command, 'version') self.assertEqual(dm.Magic, Settings.MAGIC) checksum = Message.GetChecksum(dm.Payload) self.assertEqual(checksum, dm.Checksum) deserialized_version = IOHelper.AsSerializableWithType( dm.Payload, 'neo.Network.Payloads.VersionPayload.VersionPayload') self.assertEqual(deserialized_version.Port, self.port) self.assertEqual(deserialized_version.UserAgent, self.ua) self.assertEqual(deserialized_version.Timestamp, self.payload.Timestamp)
def DeserializeFromBufer(buffer, offset=0): mstream = MemoryStream(buffer, offset) reader = BinaryReader(mstream) return Transaction.DeserializeFrom(reader)
def __init__(self): super(ScriptBuilder, self).__init__() self.ms = MemoryStream() # MemoryStream
class ScriptBuilder(object): """docstring for ScriptBuilder""" def __init__(self): super(ScriptBuilder, self).__init__() self.ms = MemoryStream() # MemoryStream def WriteUInt16(self, value, endian="<"): return self.pack('%sH' % endian, value) def WriteUInt32(self, value, endian="<"): return self.pack('%sI' % endian, value) def WriteUInt64(self, value, endian="<"): return self.pack('%sQ' % endian, value) def WriteVarInt(self, value, endian="<"): if not isinstance(value, int): raise TypeError('%s not int type.' % value) if value < 0: raise Exception('%d too small.' % value) elif value < 0xfd: return self.WriteByte(value) elif value <= 0xffff: self.WriteByte(0xfd) return self.WriteUInt16(value, endian) elif value <= 0xFFFFFFFF: self.WriteByte(0xfd) return self.WriteUInt32(value, endian) else: self.WriteByte(0xff) return self.WriteUInt64(value, endian) def WriteVarBytes(self, value, endian="<", unhexlify=True): length = len(value) self.WriteVarInt(length, endian) return self.WriteBytes(value) def WriteByte(self, value): if type(value) is bytes: self.ms.write(value) elif type(value) is str: self.ms.write(value.encode('utf-8')) elif type(value) is int: self.ms.write(bytes([value])) def WriteBytes(self, value): try: value = binascii.unhexlify(value) except TypeError: pass except binascii.Error: pass self.ms.write(value) def WriteBool(self, value, endian="<"): if value: self.add(PUSHT) else: self.add(PUSHF) def pack(self, fmt, data): return self.WriteBytes(struct.pack(fmt, data)) def add(self, op): if isinstance(op, int): self.ms.write(bytes([op])) else: self.ms.write(op) return def push(self, data): if data == None: return if type(data) is bool: return self.add(data) if type(data) is int or type(data) is BigInteger: if data == -1: return self.add(PUSHM1) elif data == 0: return self.add(PUSH0) elif data > 0 and data <= 16: return self.add(int.from_bytes(PUSH1, 'little') - 1 + data) else: return self.push(binascii.hexlify(base256_encode(data))) else: if not type(data) == bytearray: buf = binascii.unhexlify(data) else: buf = bytes(data) if len(buf) <= int.from_bytes(PUSHBYTES75, 'big'): self.add(len(buf)) self.add(buf) elif len(buf) < 0x100: self.add(PUSH1) self.add(len(buf)) self.add(buf) elif len(buf) < 0x10000: self.add(PUSH2) self.add(len(buf) & 0xff) self.add(len(buf) >> 8) self.add(buf) elif len(buf) < 0x100000000: self.add(PUSH4) self.add(len(buf) & 0xff) self.add((len(buf) >> 8) & 0xff) self.add((len(buf) >> 16) & 0xff) self.add(len(buf) >> 24) self.add(buf) return def WriteVarData(self, data): length = len(data) if length <= 75: self.WriteByte(length) elif length < 0x100: self.ms.write(PUSHDATA1) self.WriteByte(length) elif length < 0x1000: self.ms.write(PUSHDATA2) self.WriteBytes(length.to_bytes(2, 'little')) elif length < 0x10000: self.ms.write(PUSHDATA4) self.WriteBytes(length.to_bytes(4, 'little')) self.WriteBytes(data) def Emit(self, op, arg=None): self.ms.write(op) if arg is not None: self.ms.write(arg) def EmitPushBigInteger(self, number): if number == -1: return self.Emit(PUSHM1) if number == 0: return self.Emit(PUSH0) if number > 0 and number <= 16: return self.Emit(int.from_bytes(PUSH1, 'little') - 1 + number) return self.Emit(number) def EmitAppCall(self, scriptHash, useTailCall=False): if len(scriptHash) != 20: raise Exception("Invalid script") if useTailCall: return self.Emit(TAILCALL, scriptHash) return self.Emit(APPCALL, scriptHash) def EmitSysCall(self, api): if api is None: raise Exception("Please specify an api") api_bytes = bytearray(api.encode('utf-8')) length = len(api_bytes) length_bytes = bytearray(length.to_bytes(1, 'little')) out = length_bytes + api_bytes return self.Emit(SYSCALL, out) def EmitSysCallWithArguments(self, api, args): args.reverse() for argument in args: if type(argument) is bool: self.WriteBool(argument) elif type(argument) is bytes and len(argument) == 1: self.WriteByte(argument) else: self.push(binascii.hexlify(argument)) self.EmitSysCall(api) def ToArray(self, cleanup=True): retval = self.ms.ToArray() if cleanup: self.ms.Cleanup() self.ms = None return retval
class ScriptBuilder: """docstring for ScriptBuilder""" def __init__(self): super(ScriptBuilder, self).__init__() self.ms = MemoryStream() # MemoryStream def WriteUInt16(self, value, endian="<"): return self.pack('%sH' % endian, value) def WriteUInt32(self, value, endian="<"): return self.pack('%sI' % endian, value) def WriteUInt64(self, value, endian="<"): return self.pack('%sQ' % endian, value) def WriteVarInt(self, value, endian="<"): if not isinstance(value, int): raise TypeError('%s not int type.' % value) if value < 0: raise Exception('%d too small.' % value) elif value < 0xfd: return self.WriteByte(value) elif value <= 0xffff: self.WriteByte(0xfd) return self.WriteUInt16(value, endian) elif value <= 0xFFFFFFFF: self.WriteByte(0xfe) return self.WriteUInt32(value, endian) else: self.WriteByte(0xff) return self.WriteUInt64(value, endian) def WriteVarBytes(self, value, endian="<", unhexlify=True): length = len(value) self.WriteVarInt(length, endian) return self.WriteBytes(value) def WriteByte(self, value): if type(value) is bytes: self.ms.write(value) elif type(value) is str: self.ms.write(value.encode('utf-8')) elif type(value) is int: self.ms.write(bytes([value])) def WriteBytes(self, value): try: value = binascii.unhexlify(value) except TypeError: pass except binascii.Error: pass self.ms.write(value) def WriteBool(self, value, endian="<"): if value: self.add(PUSHT) else: self.add(PUSHF) def pack(self, fmt, data): return self.WriteBytes(struct.pack(fmt, data)) def add(self, op): if isinstance(op, int): self.ms.write(bytes([op])) else: self.ms.write(op) return def push(self, data): if data is None: return if type(data) is bool: return self.add(data) if type(data) is int or type(data) is BigInteger: if data == -1: return self.add(PUSHM1) elif data == 0: return self.add(PUSH0) elif data > 0 and data <= 16: return self.add(int.from_bytes(PUSH1, 'little') - 1 + data) else: return self.push(binascii.hexlify(data.ToByteArray())) else: if not type(data) == bytearray: buf = binascii.unhexlify(data) else: buf = bytes(data) if len(buf) <= int.from_bytes(PUSHBYTES75, 'big'): self.add(len(buf)) self.add(buf) elif len(buf) < 0x100: self.add(PUSHDATA1) self.add(len(buf)) self.add(buf) elif len(buf) < 0x10000: self.add(PUSHDATA2) self.add(len(buf) & 0xff) self.add(len(buf) >> 8) self.add(buf) elif len(buf) < 0x100000000: self.add(PUSHDATA4) self.add(len(buf) & 0xff) self.add((len(buf) >> 8) & 0xff) self.add((len(buf) >> 16) & 0xff) self.add(len(buf) >> 24) self.add(buf) return def WriteVarData(self, data): length = len(data) if length <= 75: self.WriteByte(length) elif length < 0x100: self.ms.write(PUSHDATA1) self.WriteByte(length) elif length < 0x1000: self.ms.write(PUSHDATA2) self.WriteBytes(length.to_bytes(2, 'little')) elif length < 0x10000: self.ms.write(PUSHDATA4) self.WriteBytes(length.to_bytes(4, 'little')) self.WriteBytes(data) def Emit(self, op, arg=None): self.ms.write(op) if arg is not None: self.ms.write(arg) def EmitPushBigInteger(self, number): if number == -1: return self.Emit(PUSHM1) if number == 0: return self.Emit(PUSH0) if number > 0 and number <= 16: return self.Emit(int.from_bytes(PUSH1, 'little') - 1 + number) return self.Emit(number) def EmitAppCall(self, scriptHash, useTailCall=False): if len(scriptHash) != 20: raise Exception("Invalid script") if useTailCall: return self.Emit(TAILCALL, scriptHash) return self.Emit(APPCALL, scriptHash) def EmitAppCallWithOperationAndData(self, script_hash, operation, data): self.push(data) self.push(operation.encode('utf-8').hex()) self.Emit(APPCALL, script_hash.Data) def EmitAppCallWithOperationAndArgs(self, script_hash, operation, args): args.reverse() for i in args: self.push(i) self.push(len(args)) self.Emit(PACK) self.push(operation.encode('utf-8').hex()) self.Emit(APPCALL, script_hash.Data) def EmitAppCallWithOperation(self, script_hash, operation): self.push(False) self.push(operation.encode('utf-8').hex()) self.Emit(APPCALL, script_hash.Data) def EmitAppCallWithJsonArgs(self, script_hash, args): args.reverse() for a in args: if isinstance(a.Value, list): a.Value.reverse() for item in a.Value: self.push(item.ToVM()) self.push(len(a.Value)) self.Emit(PACK) else: self.push(a.ToVM()) self.Emit(APPCALL, script_hash.Data) def EmitSysCall(self, api): if api is None: raise Exception("Please specify an api") api_bytes = bytearray(api.encode('utf-8')) length = len(api_bytes) length_bytes = bytearray(length.to_bytes(1, 'little')) out = length_bytes + api_bytes return self.Emit(SYSCALL, out) def EmitSysCallWithArguments(self, api, args): args.reverse() for argument in args: if type(argument) is bool: self.WriteBool(argument) elif type(argument) is bytes and len(argument) == 1: self.WriteByte(argument) else: self.push(binascii.hexlify(argument)) self.EmitSysCall(api) def ToArray(self, cleanup=True): retval = self.ms.ToArray() if cleanup: self.ms.Cleanup() self.ms = None return retval