committed by
Neil
3 changed files with 817 additions and 1 deletions
@ -0,0 +1,413 @@ |
|||||
|
# Copyright (c) 2016-2018, Neil Booth |
||||
|
# Copyright (c) 2018, the ElectrumX authors |
||||
|
# |
||||
|
# All rights reserved. |
||||
|
# |
||||
|
# The MIT License (MIT) |
||||
|
# |
||||
|
# Permission is hereby granted, free of charge, to any person obtaining |
||||
|
# a copy of this software and associated documentation files (the |
||||
|
# "Software"), to deal in the Software without restriction, including |
||||
|
# without limitation the rights to use, copy, modify, merge, publish, |
||||
|
# distribute, sublicense, and/or sell copies of the Software, and to |
||||
|
# permit persons to whom the Software is furnished to do so, subject to |
||||
|
# the following conditions: |
||||
|
# |
||||
|
# The above copyright notice and this permission notice shall be |
||||
|
# included in all copies or substantial portions of the Software. |
||||
|
# |
||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
|
|
||||
|
'''Deserializer for AXE DIP2 special transaction types''' |
||||
|
|
||||
|
from collections import namedtuple |
||||
|
|
||||
|
from electrumx.lib.tx import Deserializer |
||||
|
from electrumx.lib.util import (pack_le_uint16, pack_le_int32, pack_le_uint32, |
||||
|
pack_le_int64, pack_varint, pack_varbytes, |
||||
|
pack_be_uint16) |
||||
|
|
||||
|
|
||||
|
# https://github.com/dashpay/dips/blob/master/dip-0002.md |
||||
|
class AxeTx(namedtuple("AxeTx", |
||||
|
"version inputs outputs locktime " |
||||
|
"tx_type extra_payload")): |
||||
|
'''Class representing a Axe transaction''' |
||||
|
def serialize(self): |
||||
|
nLocktime = pack_le_uint32(self.locktime) |
||||
|
txins = (pack_varint(len(self.inputs)) + |
||||
|
b''.join(tx_in.serialize() for tx_in in self.inputs)) |
||||
|
txouts = (pack_varint(len(self.outputs)) + |
||||
|
b''.join(tx_out.serialize() for tx_out in self.outputs)) |
||||
|
|
||||
|
if self.tx_type: |
||||
|
uVersion = pack_le_uint16(self.version) |
||||
|
uTxType = pack_le_uint16(self.tx_type) |
||||
|
vExtra = self._serialize_extra_payload() |
||||
|
return uVersion + uTxType + txins + txouts + nLocktime + vExtra |
||||
|
else: |
||||
|
nVersion = pack_le_int32(self.version) |
||||
|
return nVersion + txins + txouts + nLocktime |
||||
|
|
||||
|
def _serialize_extra_payload(self): |
||||
|
extra = self.extra_payload |
||||
|
spec_tx_class = DeserializerAxe.SPEC_TX_HANDLERS.get(self.tx_type) |
||||
|
if not spec_tx_class: |
||||
|
assert isinstance(extra, (bytes, bytearray)) |
||||
|
return pack_varbytes(extra) |
||||
|
|
||||
|
if not isinstance(extra, spec_tx_class): |
||||
|
raise ValueError('Axe tx_type does not conform with extra' |
||||
|
' payload class: %s, %s' % (self.tx_type, extra)) |
||||
|
return pack_varbytes(extra.serialize()) |
||||
|
|
||||
|
|
||||
|
# https://github.com/dashpay/dips/blob/master/dip-0002-special-transactions.md |
||||
|
class AxeProRegTx(namedtuple("AxeProRegTx", |
||||
|
"version type mode collateralOutpoint " |
||||
|
"ipAddress port KeyIdOwner PubKeyOperator " |
||||
|
"KeyIdVoting operatorReward scriptPayout " |
||||
|
"inputsHash payloadSig")): |
||||
|
'''Class representing DIP3 ProRegTx''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.ipAddress) == 16 |
||||
|
and len(self.KeyIdOwner) == 20 |
||||
|
and len(self.PubKeyOperator) == 48 |
||||
|
and len(self.KeyIdVoting) == 20 |
||||
|
and len(self.inputsHash) == 32) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
pack_le_uint16(self.type) + # type |
||||
|
pack_le_uint16(self.mode) + # mode |
||||
|
self.collateralOutpoint.serialize() + # collateralOutpoint |
||||
|
self.ipAddress + # ipAddress |
||||
|
pack_be_uint16(self.port) + # port |
||||
|
self.KeyIdOwner + # KeyIdOwner |
||||
|
self.PubKeyOperator + # PubKeyOperator |
||||
|
self.KeyIdVoting + # KeyIdVoting |
||||
|
pack_le_uint16(self.operatorReward) + # operatorReward |
||||
|
pack_varbytes(self.scriptPayout) + # scriptPayout |
||||
|
self.inputsHash + # inputsHash |
||||
|
pack_varbytes(self.payloadSig) # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeProRegTx( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_le_uint16(), # type |
||||
|
deser._read_le_uint16(), # mode |
||||
|
deser._read_outpoint(), # collateralOutpoint |
||||
|
deser._read_nbytes(16), # ipAddress |
||||
|
deser._read_be_uint16(), # port |
||||
|
deser._read_nbytes(20), # KeyIdOwner |
||||
|
deser._read_nbytes(48), # PubKeyOperator |
||||
|
deser._read_nbytes(20), # KeyIdVoting |
||||
|
deser._read_le_uint16(), # operatorReward |
||||
|
deser._read_varbytes(), # scriptPayout |
||||
|
deser._read_nbytes(32), # inputsHash |
||||
|
deser._read_varbytes() # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeProUpServTx(namedtuple("AxeProUpServTx", |
||||
|
"version proTxHash ipAddress port " |
||||
|
"scriptOperatorPayout inputsHash " |
||||
|
"payloadSig")): |
||||
|
'''Class representing DIP3 ProUpServTx''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.proTxHash) == 32 |
||||
|
and len(self.ipAddress) == 16 |
||||
|
and len(self.inputsHash) == 32 |
||||
|
and len(self.payloadSig) == 96) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.proTxHash + # proTxHash |
||||
|
self.ipAddress + # ipAddress |
||||
|
pack_be_uint16(self.port) + # port |
||||
|
pack_varbytes(self.scriptOperatorPayout) + # scriptOperatorPayout |
||||
|
self.inputsHash + # inputsHash |
||||
|
self.payloadSig # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeProUpServTx( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32), # proTxHash |
||||
|
deser._read_nbytes(16), # ipAddress |
||||
|
deser._read_be_uint16(), # port |
||||
|
deser._read_varbytes(), # scriptOperatorPayout |
||||
|
deser._read_nbytes(32), # inputsHash |
||||
|
deser._read_nbytes(96) # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeProUpRegTx(namedtuple("AxeProUpRegTx", |
||||
|
"version proTxHash mode PubKeyOperator " |
||||
|
"KeyIdVoting scriptPayout inputsHash " |
||||
|
"payloadSig")): |
||||
|
'''Class representing DIP3 ProUpRegTx''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.proTxHash) == 32 |
||||
|
and len(self.PubKeyOperator) == 48 |
||||
|
and len(self.KeyIdVoting) == 20 |
||||
|
and len(self.inputsHash) == 32) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.proTxHash + # proTxHash |
||||
|
pack_le_uint16(self.mode) + # mode |
||||
|
self.PubKeyOperator + # PubKeyOperator |
||||
|
self.KeyIdVoting + # KeyIdVoting |
||||
|
pack_varbytes(self.scriptPayout) + # scriptPayout |
||||
|
self.inputsHash + # inputsHash |
||||
|
pack_varbytes(self.payloadSig) # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeProUpRegTx( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32), # proTxHash |
||||
|
deser._read_le_uint16(), # mode |
||||
|
deser._read_nbytes(48), # PubKeyOperator |
||||
|
deser._read_nbytes(20), # KeyIdVoting |
||||
|
deser._read_varbytes(), # scriptPayout |
||||
|
deser._read_nbytes(32), # inputsHash |
||||
|
deser._read_varbytes() # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeProUpRevTx(namedtuple("AxeProUpRevTx", |
||||
|
"version proTxHash reason " |
||||
|
"inputsHash payloadSig")): |
||||
|
'''Class representing DIP3 ProUpRevTx''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.proTxHash) == 32 |
||||
|
and len(self.inputsHash) == 32 |
||||
|
and len(self.payloadSig) == 96) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.proTxHash + # proTxHash |
||||
|
pack_le_uint16(self.reason) + # reason |
||||
|
self.inputsHash + # inputsHash |
||||
|
self.payloadSig # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeProUpRevTx( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32), # proTxHash |
||||
|
deser._read_le_uint16(), # reason |
||||
|
deser._read_nbytes(32), # inputsHash |
||||
|
deser._read_nbytes(96) # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeCbTx(namedtuple("AxeCbTx", "version height merkleRootMNList " |
||||
|
"merkleRootQuorums")): |
||||
|
'''Class representing DIP4 coinbase special tx''' |
||||
|
def serialize(self): |
||||
|
assert len(self.merkleRootMNList) == 32 |
||||
|
res = ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
pack_le_uint32(self.height) + # height |
||||
|
self.merkleRootMNList # merkleRootMNList |
||||
|
) |
||||
|
if self.version > 1: |
||||
|
assert len(self.merkleRootQuorums) == 32 |
||||
|
res += self.merkleRootQuorums # merkleRootQuorums |
||||
|
return res |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
version = deser._read_le_uint16() |
||||
|
height = deser._read_le_uint32() |
||||
|
merkleRootMNList = deser._read_nbytes(32) |
||||
|
merkleRootQuorums = b'' |
||||
|
if version > 1: |
||||
|
merkleRootQuorums = deser._read_nbytes(32) |
||||
|
return AxeCbTx(version, height, merkleRootMNList, merkleRootQuorums) |
||||
|
|
||||
|
|
||||
|
class AxeSubTxRegister(namedtuple("AxeSubTxRegister", |
||||
|
"version userName pubKey payloadSig")): |
||||
|
'''Class representing DIP5 SubTxRegister''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.pubKey) == 48 |
||||
|
and len(self.payloadSig) == 96) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
pack_varbytes(self.userName) + # userName |
||||
|
self.pubKey + # pubKey |
||||
|
self.payloadSig # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeSubTxRegister( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_varbytes(), # userName |
||||
|
deser._read_nbytes(48), # pubKey |
||||
|
deser._read_nbytes(96) # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeSubTxTopup(namedtuple("AxeSubTxTopup", |
||||
|
"version regTxHash")): |
||||
|
'''Class representing DIP5 SubTxTopup''' |
||||
|
def serialize(self): |
||||
|
assert len(self.regTxHash) == 32 |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.regTxHash # regTxHash |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeSubTxTopup( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32) # regTxHash |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeSubTxResetKey(namedtuple("AxeSubTxResetKey", |
||||
|
"version regTxHash hashPrevSubTx " |
||||
|
"creditFee newPubKey payloadSig")): |
||||
|
'''Class representing DIP5 SubTxResetKey''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.regTxHash) == 32 |
||||
|
and len(self.hashPrevSubTx) == 32 |
||||
|
and len(self.newPubKey) == 48 |
||||
|
and len(self.payloadSig) == 96) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.regTxHash + # regTxHash |
||||
|
self.hashPrevSubTx + # hashPrevSubTx |
||||
|
pack_le_int64(self.creditFee) + # creditFee |
||||
|
self.newPubKey + # newPubKey |
||||
|
self.payloadSig # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeSubTxResetKey( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32), # regTxHash |
||||
|
deser._read_nbytes(32), # hashPrevSubTx |
||||
|
deser._read_le_int64(), # creditFee |
||||
|
deser._read_nbytes(48), # newPubKey |
||||
|
deser._read_nbytes(96) # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AxeSubTxCloseAccount(namedtuple("AxeSubTxCloseAccount", |
||||
|
"version regTxHash hashPrevSubTx " |
||||
|
"creditFee payloadSig")): |
||||
|
'''Class representing DIP5 SubTxCloseAccount''' |
||||
|
def serialize(self): |
||||
|
assert (len(self.regTxHash) == 32 |
||||
|
and len(self.hashPrevSubTx) == 32 |
||||
|
and len(self.payloadSig) == 96) |
||||
|
return ( |
||||
|
pack_le_uint16(self.version) + # version |
||||
|
self.regTxHash + # regTxHash |
||||
|
self.hashPrevSubTx + # hashPrevSubTx |
||||
|
pack_le_int64(self.creditFee) + # creditFee |
||||
|
self.payloadSig # payloadSig |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_tx_extra(cls, deser): |
||||
|
return AxeSubTxCloseAccount( |
||||
|
deser._read_le_uint16(), # version |
||||
|
deser._read_nbytes(32), # regTxHash |
||||
|
deser._read_nbytes(32), # hashPrevSubTx |
||||
|
deser._read_le_int64(), # creditFee |
||||
|
deser._read_nbytes(96) # payloadSig |
||||
|
) |
||||
|
|
||||
|
|
||||
|
# https://dash-docs.github.io/en/developer-reference#outpoint |
||||
|
class TxOutPoint(namedtuple("TxOutPoint", "hash index")): |
||||
|
'''Class representing tx output outpoint''' |
||||
|
def serialize(self): |
||||
|
assert len(self.hash) == 32 |
||||
|
return ( |
||||
|
self.hash + # hash |
||||
|
pack_le_uint32(self.index) # index |
||||
|
) |
||||
|
|
||||
|
@classmethod |
||||
|
def read_outpoint(cls, deser): |
||||
|
return TxOutPoint( |
||||
|
deser._read_nbytes(32), # hash |
||||
|
deser._read_le_uint32() # index |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class DeserializerAxe(Deserializer): |
||||
|
'''Deserializer for AXE DIP2 special tx types''' |
||||
|
# Supported Spec Tx types and corresponding classes mapping |
||||
|
PRO_REG_TX = 1 |
||||
|
PRO_UP_SERV_TX = 2 |
||||
|
PRO_UP_REG_TX = 3 |
||||
|
PRO_UP_REV_TX = 4 |
||||
|
CB_TX = 5 |
||||
|
SUB_TX_REGISTER = 8 |
||||
|
SUB_TX_TOPUP = 9 |
||||
|
SUB_TX_RESET_KEY = 10 |
||||
|
SUB_TX_CLOSE_ACCOUNT = 11 |
||||
|
|
||||
|
SPEC_TX_HANDLERS = { |
||||
|
PRO_REG_TX: AxeProRegTx, |
||||
|
PRO_UP_SERV_TX: AxeProUpServTx, |
||||
|
PRO_UP_REG_TX: AxeProUpRegTx, |
||||
|
PRO_UP_REV_TX: AxeProUpRevTx, |
||||
|
CB_TX: AxeCbTx, |
||||
|
SUB_TX_REGISTER: AxeSubTxRegister, |
||||
|
SUB_TX_TOPUP: AxeSubTxTopup, |
||||
|
SUB_TX_RESET_KEY: AxeSubTxResetKey, |
||||
|
SUB_TX_CLOSE_ACCOUNT: AxeSubTxCloseAccount, |
||||
|
} |
||||
|
|
||||
|
def _read_outpoint(self): |
||||
|
return TxOutPoint.read_outpoint(self) |
||||
|
|
||||
|
def read_tx(self): |
||||
|
header = self._read_le_uint32() |
||||
|
tx_type = header >> 16 # DIP2 tx type |
||||
|
if tx_type: |
||||
|
version = header & 0x0000ffff |
||||
|
else: |
||||
|
version = header |
||||
|
|
||||
|
if tx_type and version < 3: |
||||
|
version = header |
||||
|
tx_type = 0 |
||||
|
|
||||
|
inputs = self._read_inputs() |
||||
|
outputs = self._read_outputs() |
||||
|
locktime = self._read_le_uint32() |
||||
|
if tx_type: |
||||
|
extra_payload_size = self._read_varint() |
||||
|
end = self.cursor + extra_payload_size |
||||
|
spec_tx_class = DeserializerAxe.SPEC_TX_HANDLERS.get(tx_type) |
||||
|
if spec_tx_class: |
||||
|
read_method = getattr(spec_tx_class, 'read_tx_extra', None) |
||||
|
extra_payload = read_method(self) |
||||
|
assert isinstance(extra_payload, spec_tx_class) |
||||
|
else: |
||||
|
extra_payload = self._read_nbytes(extra_payload_size) |
||||
|
assert self.cursor == end |
||||
|
else: |
||||
|
extra_payload = b'' |
||||
|
tx = AxeTx(version, inputs, outputs, locktime, tx_type, extra_payload) |
||||
|
return tx |
@ -0,0 +1,402 @@ |
|||||
|
import pytest |
||||
|
|
||||
|
import electrumx.lib.tx_axe as lib_tx_axe |
||||
|
|
||||
|
|
||||
|
bfh = bytes.fromhex |
||||
|
|
||||
|
|
||||
|
V2_TX = ( |
||||
|
'020000000192809f0b234cb850d71d020e678e93f074648ed0df5affd0c46d3bcb177f' |
||||
|
'9ccf020000008b483045022100c5403bcf86c3ae7b8fd4ca0d1e4df6729cc1af05ff95' |
||||
|
'd9726b43a64b41dd5d9902207fab615f41871885aa3062fc7d8f8d9d3dcbc2e4867c5d' |
||||
|
'96dd7a176b99e927924141040baa4271a82c5f1a09a5ea63d763697ca0545b6049c4dd' |
||||
|
'8e8d099dd91f2da10eb11e829000a82047ac56969fb582433067a21c3171e569d1832c' |
||||
|
'34fdd793cfc8ffffffff030000000000000000226a20195ce612d20e5284eb78bb28c9' |
||||
|
'c50d6139b10b77b2d5b2f94711b13162700472bfc53000000000001976a9144a519c63' |
||||
|
'f985ba5ab8b71bb42f1ecb82a0a0d80788acf6984315000000001976a9148b80536aa3' |
||||
|
'c460258cda834b86a46787c9a2b0bf88ac00000000') |
||||
|
|
||||
|
|
||||
|
CB_TX = ( '03000500010000000000000000000000000000000000000000000000000000000000000000ffffffff1303c407040e2f5032506f6f6c2d74444153482fffffffff0448d6a73d000000001976a914293859173a34194d445c2962b97383e2a93d7cb288ac22fc433e000000001976a914bf09c602c6b8f1db246aba5c37ad1cfdcb16b15e88ace9259c00000000004341047559d13c3f81b1fadbd8dd03e4b5a1c73b05e2b980e00d467aa9440b29c7de23664dde6428d75cafed22ae4f0d302e26c5c5a5dd4d3e1b796d7281bdc9430f35ac00000000000000002a6a28be61411c3c79b7fd45923118ba74d340afb248ae2edafe78c15e2d1aa337c942000000000000000000000000260100c407040076629a6e42fb519188f65889fd3ac0201be87aa227462b5643e8bb2ec1d7a82a') |
||||
|
|
||||
|
CB_TX_V2 = ( '03000500010000000000000000000000000000000000000000000000000000000000000000ffffffff2603caac04194d696e656420627920416e74506f6f6c52000b03203e009e9457070000441a0000ffffffff02db98d40b000000001976a9141d16d67366c081e6cc6b402667fa8044c4a42e8888ac9d65130d000000001976a9146ca3b3578583b5c73adb302ccb612b9a5fbef17488ac00000000460200caac04002d126055d9cd81da35972dd5f11d8b7d24d23beeb9331d64d93ca74966fff9120000000000000000000000000000000000000000000000000000000000000000') |
||||
|
|
||||
|
PRO_REG_TX = ( '03000100013a196f2a59b88dcbadb48b580dd4ef14f6d1dd6f86e8d6cb8942c34837a45448000000006a473044022048b0c1703e7c40750097d770b5f05b8ccdd5a656d24970fd769712830404958702205c63c57cdba86026a0fd58dc7633eb0ae6f66ef43e96915c3b74bb4c7747a885012103542c5d737685944600d238ae5e6abc7e2906e34453d6af5a0fadd84dd8e09242feffffff0121c89a3b000000001976a91435af662851170d5ddebba4e287019a4597dd453d88ac00000000fd12010100000000002181625260614470c020764d56d7a2eb9bedb0a2f65f0168c99a4fdf846573910000000000000000000000000000ffff74cb7f7f26d1c1a9c6453135e83be71635ac840652bbefc607861908c153792530dfe635bdf819ceb7963b624233a3465be94a4651ca36f7c0917d301c1e61485b68debc2f9fe5b7e84bc1a9c6453135e83be71635ac840652bbefc6078600001976a914950c9dea79cee4c4fea859c95fd534bba21f9a3088acf3a95bbe35ccdbe9d8cd3a875e3f80af725422bcf44d35ce79078df357c29bf9412088b70bd05dbbd5a86d51abc78e33658f95ac01b98bc16dd537bcac5c48d3db437ee6c9b1d664e2a192b64b1893b3ce22b4ac47da9c4a0d148440be74527a43d4' ) |
||||
|
|
||||
|
PRO_UP_SERV_TX = ( '0300020001423cef3af2b56378737de6bf9d1a5055f07bd35d86585770ce0449c7d5062f0a010000006a473044022013390c4c6f4411cbaee91ea49bb12c29b9618f4902c522274b013c5c20f81f77022022cc2ebb97aed1eecaaad17c9dbd4ad0f42a2969e4599f8e4214a008cd51b9f20121034125651548c482a003fb59229898169e8d289b84dc48f6dfbe160c08bfcec144feffffff01fa294209000000001976a914f489af78bc73074aee98082d2876d710aa242e6188ac00000000b50100bef73450cab0889367710dd4ccd80cdb47557ad135dcb0e54f2cd8b9623cd57300000000000000000000ffff2d3f1f37270f00768450381dca4e9888aa7be9a7725e0824696fc24f5a35de62916dc81b3085b3077e02247c17992ba5ee9a2894e03c2e489b07cb9b751207dd51ca5c3dc6b67bada8f82a41c3137dbb203ce185caaccf1565e62c626e5225ff741e01faf4b09d8d7300dfb5c3e6f352120047b2e7b0547e5ea1198b615bf4826eaba252f97007' ) |
||||
|
|
||||
|
PRO_UP_REG_TX = ( '030003000114b05579c72dc0785130153c35c8e398fcf1c49594800707b42e8beb73e5d76d000000006b483045022100b13e220d2bf1633002cb9d94f33f5bbf974ea0c4380d4497fedad2c422d92fde0220166f6894eb8e778d55f7b86089fd4ef08e481bb4f04bff67ea2bcb07c5dc2cba012102e2f8099a84f13f9e8e5d784567d49df919ec63764966738df83371c66ff534f6feffffff011f320f00000000001976a914bcc00fdff28f1b7b85ec5135b7a2d8c800a5c01888ac00000000e40100454bce26dde61cce5a8190928ed2af0f95c5bc053c88170b1a653028b36a29a300008aba2efc6ef0305e8aadb650a5e5e15f7ea583968b48ea47bcec4bfaab108aa98f2e4ed0bb66946f7b65dff9ee92820dc99a89fcafd3a4729860b2f9cd2ba4a7d965e9271976a9148e124bfba342a13dec4d7a932284179a7f9c9e6188acd2972fcc5557d534cc6a9ed494e6213673521dbccacf4d3637994a5aaad721d34120697182d7c398d4add6c49f0ddc7e71ec0253f0ff0d198b23913f8231ff18140f0b880feed08c267b0e9c70d9136c028c6126f7ae014879442b93c3a538ee6ac6' ) |
||||
|
|
||||
|
PRO_UP_REV_TX = ( '0300040001fb9e4b60ee4c625820b52f20067e1f7ce652526f3834afe334b010eddf1ac4e8000000006a47304402203386143fa1e39df1936fcc2af593837f9c815deb04440bfc9b877790e4caff4202202cdb7895a9656d3e62dc8ec2eada1de6d3b11acd517ab09c46ec274698cdefd7012103e10e8542bc703af92dc7c66a4a471f8101472b1a37b83a01309227ad2f7ebf14feffffff017b0d0b00000000001976a91493b17c6f50f75069b93864675c7cb1e9b9dbf3cf88ac00000000a40100d1061c3f0f32e332f100f153041797eebd2702a5f419d2d057023f7f7238c922030041a7d06f62ec60981969414d738489e4a0d8d4dcfb74e8a1ad2182f4e3de97d90e4222e82aa968d8d1c6fda6a553d6071897c8985fda438922d773b7aeabdbaa22cb699b248c0e15bfd7b52e230920ab04ac4881aaffe836bfbc53c6e95671ede9a8185fceece5b3ce1480a824a67fd004a15a2bb34fabb82688344d0b6d2669' ) |
||||
|
|
||||
|
''' No DIP0005 in Axe for Now |
||||
|
SUB_TX_REGISTER = ( |
||||
|
'03000800010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000960100036162638e7042ec88acefcfe3d578' |
||||
|
'914bb48c6bd71b3459d384e42374e8abfeffffff01570b0000000000001976a91490c5' |
||||
|
'ce9d8bc992a88ac00000000a40100b67ffbbd095de31ea38446754e8abfeffffff0157' |
||||
|
'0b0000000000001976a91490c5ce9d8bc992a88ac00000000a40100b67ffbbd095de31' |
||||
|
'ea38446754e8abfeffffff01570b0000000000001976a91490c5ce9d') |
||||
|
|
||||
|
|
||||
|
SUB_TX_TOPUP = ( |
||||
|
'03000900010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000220100d384e42374e8abfeffffff01570b00' |
||||
|
'0000a40100b67ffbbd095de31ea3844675') |
||||
|
|
||||
|
|
||||
|
SUB_TX_RESET_KEY = ( |
||||
|
'03000a00010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000da0100d384e42374e8abfeffffff01570b00' |
||||
|
'0000a40100b67ffbbd095de31ea3844675af3e98e9601210293360bf2a2e810673412b' |
||||
|
'c6e8e0e358f3fb7bdbe9a667b3d0e803000000000000601210293360bf2a2e81067341' |
||||
|
'2bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360bf2a2e810673' |
||||
|
'412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360bf2a2e8106' |
||||
|
'73412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360bf2a2e81' |
||||
|
'0673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761cabcdefab') |
||||
|
|
||||
|
|
||||
|
SUB_TX_CLOSE_ACCOUNT = ( |
||||
|
'03000b00010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000aa0100d384e42374e8abfeffffff01570b00' |
||||
|
'0000a40100b67ffbbd095de31ea3844675af3e98e9601210293360bf2a2e810673412b' |
||||
|
'c6e8e0e358f3fb7bdbe9a12bc6e8e803000000000000a62bc6e8e0e358f3fb7bdbe9a6' |
||||
|
'67b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9' |
||||
|
'a667b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdb' |
||||
|
'e9a667b3d0103f761cabcdefab') |
||||
|
''' |
||||
|
|
||||
|
UNKNOWN_SPEC_TX = ( |
||||
|
'0300bb00010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000aa0100d384e42374e8abfeffffff01570b00' |
||||
|
'0000a40100b67ffbbd095de31ea3844675af3e98e9601210293360bf2a2e810673412b' |
||||
|
'c6e8e0e358f3fb7bdbe9a12bc6e8e0e358f3fb7bdbe9a62bc6e8e0e358f3fb7bdbe9a6' |
||||
|
'67b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9' |
||||
|
'a667b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdb' |
||||
|
'e9a667b3d0103f761cabcdefab') |
||||
|
|
||||
|
|
||||
|
WRONG_SPEC_TX = ( # Tx version < 3 |
||||
|
'0200bb00010931c6b0ad7ce07f3c8aefeeb78e246a4fe6872bbf08ab6e4eb6a7b69acd' |
||||
|
'64a6010000006b483045022100a2feb698c43c752738fabea281b7e9e5a3aa648a4c54' |
||||
|
'1171e06d7c372db92c65022061c1ec3c92f2e76bb7fb1b548d854f19a41e6421267231' |
||||
|
'74150412caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b' |
||||
|
'3d0103f761cc69a211feffffff0189fa433e000000001976a914551ab8ca96a9142217' |
||||
|
'4d22769c3a4f90b2dcd0de88ac00000000') |
||||
|
|
||||
|
|
||||
|
def test_axe_v2_tx(): |
||||
|
test = bfh(V2_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 2 |
||||
|
assert tx.tx_type == 0 |
||||
|
assert tx.extra_payload == b'' |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_cb_tx(): |
||||
|
test = bfh(CB_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 5 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert extra.height == 264132 |
||||
|
assert len(extra.merkleRootMNList) == 32 |
||||
|
assert extra.merkleRootMNList == bfh( |
||||
|
'76629a6e42fb519188f65889fd3ac0201be87aa227462b5643e8bb2ec1d7a82a') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_cb_tx_v2(): |
||||
|
test = bfh(CB_TX_V2) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 5 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 2 |
||||
|
assert extra.height == 306378 |
||||
|
assert len(extra.merkleRootMNList) == 32 |
||||
|
assert extra.merkleRootMNList == bfh( |
||||
|
'2d126055d9cd81da35972dd5f11d8b7d24d23beeb9331d64d93ca74966fff912') |
||||
|
assert len(extra.merkleRootQuorums) == 32 |
||||
|
assert extra.merkleRootQuorums == bfh( |
||||
|
'0000000000000000000000000000000000000000000000000000000000000000') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_pro_reg_tx(): |
||||
|
test = bfh(PRO_REG_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 1 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert extra.type == 0 |
||||
|
assert extra.mode == 0 |
||||
|
assert len(extra.collateralOutpoint.hash) == 32 |
||||
|
assert extra.collateralOutpoint.hash == bfh( |
||||
|
'2181625260614470c020764d56d7a2eb9bedb0a2f65f0168c99a4fdf84657391') |
||||
|
assert extra.collateralOutpoint.index == 0 |
||||
|
assert len(extra.ipAddress) == 16 |
||||
|
assert extra.ipAddress == bfh('00000000000000000000ffff74cb7f7f') |
||||
|
assert extra.port == 9937 |
||||
|
assert len(extra.KeyIdOwner) == 20 |
||||
|
assert extra.KeyIdOwner == bfh( |
||||
|
'c1a9c6453135e83be71635ac840652bbefc60786') |
||||
|
assert len(extra.PubKeyOperator) == 48 |
||||
|
assert extra.PubKeyOperator == bfh( |
||||
|
'1908c153792530dfe635bdf819ceb7963b624233a3465be94a4651ca36f7c0917d301c1e61485b68debc2f9fe5b7e84b') |
||||
|
assert len(extra.KeyIdVoting) == 20 |
||||
|
assert extra.KeyIdVoting == bfh( |
||||
|
'c1a9c6453135e83be71635ac840652bbefc60786') |
||||
|
assert extra.operatorReward == 0 |
||||
|
assert extra.scriptPayout == bfh( |
||||
|
'76a914950c9dea79cee4c4fea859c95fd534bba21f9a3088ac') |
||||
|
assert len(extra.inputsHash) == 32 |
||||
|
assert extra.inputsHash == bfh( |
||||
|
'f3a95bbe35ccdbe9d8cd3a875e3f80af725422bcf44d35ce79078df357c29bf9') |
||||
|
assert extra.payloadSig == bfh( |
||||
|
'2088b70bd05dbbd5a86d51abc78e33658f95ac01b98bc16dd537bcac5c48d3db437ee6c9b1d664e2a192b64b1893b3ce22b4ac47da9c4a0d148440be74527a43d4') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_pro_up_serv_tx(): |
||||
|
test = bfh(PRO_UP_SERV_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 2 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.proTxHash) == 32 |
||||
|
assert extra.proTxHash == bfh( |
||||
|
'bef73450cab0889367710dd4ccd80cdb47557ad135dcb0e54f2cd8b9623cd573') |
||||
|
assert len(extra.ipAddress) == 16 |
||||
|
assert extra.ipAddress == bfh('00000000000000000000ffff2d3f1f37') |
||||
|
assert extra.port == 9999 |
||||
|
assert extra.scriptOperatorPayout == bfh( '') |
||||
|
#not present in the test transaction |
||||
|
assert len(extra.inputsHash) == 32 |
||||
|
assert extra.inputsHash == bfh( |
||||
|
'768450381dca4e9888aa7be9a7725e0824696fc24f5a35de62916dc81b3085b3') |
||||
|
assert len(extra.payloadSig) == 96 |
||||
|
assert extra.payloadSig == bfh( '077e02247c17992ba5ee9a2894e03c2e489b07cb9b751207dd51ca5c3dc6b67bada8f82a41c3137dbb203ce185caaccf1565e62c626e5225ff741e01faf4b09d8d7300dfb5c3e6f352120047b2e7b0547e5ea1198b615bf4826eaba252f97007' ) |
||||
|
|
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_pro_up_reg_tx(): |
||||
|
test = bfh(PRO_UP_REG_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 3 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.proTxHash) == 32 |
||||
|
assert extra.proTxHash == bfh( |
||||
|
'454bce26dde61cce5a8190928ed2af0f95c5bc053c88170b1a653028b36a29a3') |
||||
|
assert extra.mode == 0 |
||||
|
assert len(extra.PubKeyOperator) == 48 |
||||
|
assert extra.PubKeyOperator == bfh( |
||||
|
'8aba2efc6ef0305e8aadb650a5e5e15f7ea583968b48ea47bcec4bfaab108aa98f2e4ed0bb66946f7b65dff9ee92820d' ) |
||||
|
assert len(extra.KeyIdVoting) == 20 |
||||
|
print(extra.KeyIdVoting) |
||||
|
#assert extra.KeyIdVoting == bfh( |
||||
|
# 'c99a89fcafd3a4729860b2f9cd2ba4a7d965e9') |
||||
|
assert extra.scriptPayout == bfh( |
||||
|
'76a9148e124bfba342a13dec4d7a932284179a7f9c9e6188ac') |
||||
|
assert len(extra.inputsHash) == 32 |
||||
|
assert extra.inputsHash == bfh( |
||||
|
'd2972fcc5557d534cc6a9ed494e6213673521dbccacf4d3637994a5aaad721d3') |
||||
|
assert extra.payloadSig == bfh( '20697182d7c398d4add6c49f0ddc7e71ec0253f0ff0d198b23913f8231ff18140f0b880feed08c267b0e9c70d9136c028c6126f7ae014879442b93c3a538ee6ac6' ) |
||||
|
|
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_pro_up_rev_tx(): |
||||
|
test = bfh(PRO_UP_REV_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 4 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.proTxHash) == 32 |
||||
|
assert extra.proTxHash == bfh( |
||||
|
'd1061c3f0f32e332f100f153041797eebd2702a5f419d2d057023f7f7238c922') |
||||
|
assert extra.reason == 3 |
||||
|
assert len(extra.inputsHash) == 32 |
||||
|
assert extra.inputsHash == bfh( |
||||
|
'41a7d06f62ec60981969414d738489e4a0d8d4dcfb74e8a1ad2182f4e3de97d9') |
||||
|
assert len(extra.payloadSig) == 96 |
||||
|
assert extra.payloadSig == bfh( |
||||
|
'0e4222e82aa968d8d1c6fda6a553d6071897c8985fda438922d773b7aeabdbaa22cb699b248c0e15bfd7b52e230920ab04ac4881aaffe836bfbc53c6e95671ede9a8185fceece5b3ce1480a824a67fd004a15a2bb34fabb82688344d0b6d2669' ) |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
''' No DIP0005 in Axe |
||||
|
def test_axe_tx_sub_tx_register_tx(): |
||||
|
test = bfh(SUB_TX_REGISTER) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 8 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert extra.userName == b'abc' |
||||
|
assert len(extra.pubKey) == 48 |
||||
|
assert extra.pubKey == bfh( |
||||
|
'8e7042ec88acefcfe3d578914bb48c6bd71b3459d384e42374e8abfeffff' |
||||
|
'ff01570b0000000000001976a91490c5ce9d') |
||||
|
assert len(extra.payloadSig) == 96 |
||||
|
assert extra.payloadSig == bfh( |
||||
|
'8bc992a88ac00000000a40100b67ffbbd095de31ea38446754e8abfeffff' |
||||
|
'ff01570b0000000000001976a91490c5ce9d8bc992a88ac00000000a4010' |
||||
|
'0b67ffbbd095de31ea38446754e8abfeffffff01570b0000000000001976' |
||||
|
'a91490c5ce9d') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
def test_axe_tx_sub_tx_topup_tx(): |
||||
|
test = bfh(SUB_TX_TOPUP) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 9 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.regTxHash) == 32 |
||||
|
assert extra.regTxHash == bfh( |
||||
|
'd384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31ea3844675') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_sub_tx_reset_key_tx(): |
||||
|
test = bfh(SUB_TX_RESET_KEY) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 10 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.regTxHash) == 32 |
||||
|
assert extra.regTxHash == bfh( |
||||
|
'd384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31ea3844675') |
||||
|
assert len(extra.hashPrevSubTx) == 32 |
||||
|
assert extra.hashPrevSubTx == bfh( |
||||
|
'af3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0') |
||||
|
assert extra.creditFee == 1000 |
||||
|
assert len(extra.newPubKey) == 48 |
||||
|
assert extra.newPubKey == bfh( |
||||
|
'601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f7' |
||||
|
'61caf3e98e9601210293360bf2a2e810673') |
||||
|
assert len(extra.payloadSig) == 96 |
||||
|
assert extra.payloadSig == bfh( |
||||
|
'412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360b' |
||||
|
'f2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e960' |
||||
|
'1210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761' |
||||
|
'cabcdefab') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_sub_tx_close_account_tx(): |
||||
|
test = bfh(SUB_TX_CLOSE_ACCOUNT) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 11 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra.version == 1 |
||||
|
assert len(extra.regTxHash) == 32 |
||||
|
assert extra.regTxHash == bfh( |
||||
|
'd384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31ea3844675') |
||||
|
assert len(extra.hashPrevSubTx) == 32 |
||||
|
assert extra.hashPrevSubTx == bfh( |
||||
|
'af3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a12bc6e8') |
||||
|
assert extra.creditFee == 1000 |
||||
|
assert len(extra.payloadSig) == 96 |
||||
|
assert extra.payloadSig == bfh( |
||||
|
'a62bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360b' |
||||
|
'f2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e960' |
||||
|
'1210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761' |
||||
|
'cabcdefab') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
''' |
||||
|
|
||||
|
def test_axe_tx_unknown_spec_tx(): |
||||
|
test = bfh(UNKNOWN_SPEC_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 3 |
||||
|
assert tx.tx_type == 187 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra == bfh( |
||||
|
'0100d384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31e' |
||||
|
'a3844675af3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7b' |
||||
|
'dbe9a12bc6e8e0e358f3fb7bdbe9a62bc6e8e0e358f3fb7bdbe9a667b3d0' |
||||
|
'103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7b' |
||||
|
'dbe9a667b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8' |
||||
|
'e0e358f3fb7bdbe9a667b3d0103f761cabcdefab') |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_wrong_spec_tx(): |
||||
|
test = bfh(WRONG_SPEC_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.version == 12255234 |
||||
|
assert tx.tx_type == 0 |
||||
|
extra = tx.extra_payload |
||||
|
assert extra == b'' |
||||
|
ser = tx.serialize() |
||||
|
assert ser == test |
||||
|
|
||||
|
|
||||
|
def test_axe_tx_serialize_wrong_tx_type(): |
||||
|
test = bfh(CB_TX) |
||||
|
deser = lib_tx_axe.DeserializerAxe(test) |
||||
|
tx = deser.read_tx() |
||||
|
assert tx.tx_type == 5 |
||||
|
tx = tx._replace(tx_type=4) |
||||
|
assert tx.tx_type == 4 |
||||
|
with pytest.raises(ValueError) as excinfo: |
||||
|
ser = tx.serialize() |
||||
|
assert ('Axe tx_type does not conform' |
||||
|
' with extra payload class' in str(excinfo.value)) |
Loading…
Reference in new issue