Skip to content

Commit

Permalink
API extension to support Counterwallet (CounterpartyXCP#1005)
Browse files Browse the repository at this point in the history
* fix OP_RETURN size estimation

* Remove the forced downgrade to pubkeyhash

Bitcoin 0.13.0 allows bare multisig again

* Add extended_tx_info parameter to create_ methods

If this parameter is present, instead of returning a bare unsigned transaction hex, the API will return a JSON object with details about btc spent.  The output looks like this:

{
  "btc_fee": 28621,
  "tx_hex": "0100000001688469...088ac00000000",
  "btc_in": 7683700,
  "btc_out": 0,
  "btc_change": 7655079
}
  • Loading branch information
deweller authored Oct 12, 2017
1 parent edfa696 commit 03019e8
Show file tree
Hide file tree
Showing 13 changed files with 952 additions and 994 deletions.
7 changes: 4 additions & 3 deletions counterpartylib/lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
'multisig_dust_size', 'op_return_value', 'pubkey',
'allow_unconfirmed_inputs', 'fee', 'fee_provided',
'estimate_fee_per_kb', 'estimate_fee_per_kb_nblocks',
'unspent_tx_hash', 'custom_inputs', 'dust_return_pubkey', 'disable_utxo_locks']
'unspent_tx_hash', 'custom_inputs', 'dust_return_pubkey', 'disable_utxo_locks', 'extended_tx_info']

API_MAX_LOG_SIZE = 10 * 1024 * 1024 #max log size of 20 MB before rotation (make configurable later)
API_MAX_LOG_COUNT = 10
Expand Down Expand Up @@ -312,7 +312,7 @@ def compose_transaction(db, name, params,
allow_unconfirmed_inputs=False,
fee=None,
fee_provided=0,
unspent_tx_hash=None, custom_inputs=None, dust_return_pubkey=None, disable_utxo_locks=False):
unspent_tx_hash=None, custom_inputs=None, dust_return_pubkey=None, disable_utxo_locks=False, extended_tx_info=False):
"""Create and return a transaction."""

# Get provided pubkeys.
Expand Down Expand Up @@ -363,7 +363,8 @@ def compose_transaction(db, name, params,
fee_provided=fee_provided,
unspent_tx_hash=unspent_tx_hash, custom_inputs=custom_inputs,
dust_return_pubkey=dust_return_pubkey,
disable_utxo_locks=disable_utxo_locks)
disable_utxo_locks=disable_utxo_locks,
extended_tx_info=extended_tx_info)

def conditional_decorator(decorator, condition):
"""Checks the condition and if True applies specified decorator."""
Expand Down
41 changes: 21 additions & 20 deletions counterpartylib/lib/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def construct (db, tx_info, encoding='auto',
multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE,
op_return_value=config.DEFAULT_OP_RETURN_VALUE,
exact_fee=None, fee_provided=0, provided_pubkeys=None, dust_return_pubkey=None,
allow_unconfirmed_inputs=False, unspent_tx_hash=None, custom_inputs=None, disable_utxo_locks=False):
allow_unconfirmed_inputs=False, unspent_tx_hash=None, custom_inputs=None, disable_utxo_locks=False, extended_tx_info=False):

if estimate_fee_per_kb is None:
estimate_fee_per_kb = config.ESTIMATE_FEE_PER_KB
Expand Down Expand Up @@ -443,7 +443,10 @@ def construct (db, tx_info, encoding='auto',
if encoding == 'multisig':
data_output_size = 81 # 71 for the data
elif encoding == 'opreturn':
data_output_size = 90 # 80 for the data
# prefix + data + 10 bytes script overhead
data_output_size = len(config.PREFIX) + 10
if data is not None:
data_output_size = data_output_size + len(data)
else:
data_output_size = p2pkhsize # Pay‐to‐PubKeyHash (25 for the data?)
outputs_size = (p2pkhsize * len(destination_outputs)) + (len(data_array) * data_output_size)
Expand Down Expand Up @@ -545,24 +548,6 @@ def construct (db, tx_info, encoding='auto',
else:
change_output = None

# in bitcoin core v0.12.1 a -bytespersigop was added that messes with bare multisig transactions,
# as a safeguard we fall back to pubkeyhash encoding when unsure
# when len(inputs) > len(data_outputs) there's more bytes:sigops ratio and we can safely continue
if encoding == 'multisig' and inputs and data_output and len(inputs) < len(data_array) * 2 and util.enabled('bytespersigop'):
# if auto encoding we can do pubkeyhash encoding instead
if desired_encoding == 'auto':
return construct(db, tx_info,
encoding='pubkeyhash',
fee_per_kb=fee_per_kb,
regular_dust_size=regular_dust_size,
multisig_dust_size=multisig_dust_size,
op_return_value=op_return_value,
exact_fee=exact_fee, fee_provided=fee_provided, provided_pubkeys=provided_pubkeys,
allow_unconfirmed_inputs=allow_unconfirmed_inputs, unspent_tx_hash=unspent_tx_hash, custom_inputs=custom_inputs)
# otherwise raise exception
else:
raise exceptions.EncodingError("multisig will be rejected by Bitcoin Core >= v0.12.1, you should use `encoding=auto` or `encoding=pubkeyhash`")

# Serialise inputs and outputs.
unsigned_tx = serialise(encoding, inputs, destination_outputs,
data_output, change_output,
Expand Down Expand Up @@ -593,6 +578,14 @@ def construct (db, tx_info, encoding='auto',
parsed_source, parsed_destination, x, y, parsed_data = blocks._get_tx_info(unsigned_tx_hex)
except exceptions.BTCOnlyError:
# Skip BTC‐only transactions.
if extended_tx_info:
return {
'btc_in': btc_in,
'btc_out': destination_btc_out + data_btc_out,
'btc_change': change_quantity,
'btc_fee': final_fee,
'tx_hex': unsigned_tx_hex,
}
return unsigned_tx_hex
desired_source = script.make_canonical(desired_source)

Expand All @@ -607,6 +600,14 @@ def construct (db, tx_info, encoding='auto',

raise exceptions.TransactionError('Constructed transaction does not parse correctly: {} ≠ {}'.format(desired, parsed))

if extended_tx_info:
return {
'btc_in': btc_in,
'btc_out': destination_btc_out + data_btc_out,
'btc_change': change_quantity,
'btc_fee': final_fee,
'tx_hex': unsigned_tx_hex,
}
return unsigned_tx_hex

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
33 changes: 0 additions & 33 deletions counterpartylib/test/bytespersigop_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,39 +74,6 @@ def test_bytespersigop(server_db):
assert len(tx.vout) == 2
assert "OP_RETURN" in repr(tx.vout[0].scriptPubKey)

# ADDR[0], bytespersigop=True, desc 42 bytes, pubkeyhash encoding
# pubkeyhash because ADDR[0] only has 1 UTXO to spend from
txhex = api.compose_transaction(
server_db, 'issuance',
{'source': ADDR[0],
'asset': 'TESTING',
'quantity': 100,
'transfer_destination': None,
'divisible': False,
'description': 't' * 42},
)

tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

assert len(tx.vin) == 1
assert len(tx.vout) == 8
for i in range(7):
assert "OP_CHECKSIG" in repr(tx.vout[i].scriptPubKey)

# ADDR[0], bytespersigop=True, desc 20 bytes, FORCED multisig encoding
# will error because it's not possible, ADDR[0] only has 1 UTXO
with pytest.raises(exceptions.EncodingError):
txhex = api.compose_transaction(
server_db, 'issuance',
{'source': ADDR[0],
'asset': 'TESTING',
'quantity': 100,
'transfer_destination': None,
'divisible': False,
'description': 't' * 20},
encoding='multisig'
)

# ADDR[1], bytespersigop=True, desc 41 bytes, opreturn encoding
txhex = api.compose_transaction(
server_db, 'issuance',
Expand Down
2 changes: 1 addition & 1 deletion counterpartylib/test/estimate_fee_per_kb_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _fee_per_kb(nblocks):
sumvin = sum([int(utxos[(bitcoinlib.core.b2lx(vin.prevout.hash), vin.prevout.n)]['amount'] * 1e8) for vin in pretx.vin])
sumvout = sum([vout.nValue for vout in pretx.vout])
unsignedsize = 183
signedsize = 315
signedsize = 263

fee = int((signedsize / 1000) * (fee_per_kb_used or fee_per_kb))

Expand Down
Binary file modified counterpartylib/test/fixtures/rawtransactions.db
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@
"send": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff03361500000000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e87781e0000000000006951210262415bf04af834423d3dd7ada4dc727aa153863ef89fba5aee7fc6fbf1e58754210254da540fb2663b75e6c3cc61190ad0c2431643bab28ced783cd94079bbe72447210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053ae840dea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
},
{
"broadcast": "01000000015001af2c4c3bc2c43b6233261394910d10fb157a082d9b3038c65f2d01e4ff200000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e87ffffffff020000000000000000286a26dfa40be0870f3a17475ed261adede27ff45739c8b10035c8bbf7723074918300469ceac959398fc5f5050000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e8700000000"
"broadcast": "01000000015001af2c4c3bc2c43b6233261394910d10fb157a082d9b3038c65f2d01e4ff200000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e87ffffffff020000000000000000286a26dfa40be0870f3a17475ed261adede27ff45739c8b10035c8bbf7723074918300469ceac95939a9c9f5050000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e8700000000"
},
{
"bet": "01000000015001af2c4c3bc2c43b6233261394910d10fb157a082d9b3038c65f2d01e4ff200000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e87ffffffff03361500000000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e870000000000000000346a32dfa40be0870f3a17475ed257ff5583c6f86f39c8b10035c8bbb139707dc4ed6932b6beac2a4d8846b7feb4bf8002b88efeea07adf5050000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e8700000000"
"bet": "01000000015001af2c4c3bc2c43b6233261394910d10fb157a082d9b3038c65f2d01e4ff200000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e87ffffffff03361500000000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e870000000000000000346a32dfa40be0870f3a17475ed257ff5583c6f86f39c8b10035c8bbb139707dc4ed6932b6beac2a4d8846b7feb4bf8002b88efeeaf6aff5050000000017a9144264cfd7eb65f8cbbdba98bd9815d5461fad8d7e8700000000"
},
{
"issuance": "01000000017fe100b9f1144c65ff6479f02def936a3eb3b897113edf57cec763ef0627a1fe000000001976a914b390187ef2854422ac5e4a2eb6ffe92496bef52388acffffffff02781e00000000000069512103f216324526136068cea72482c101b243e5421a5f2b9266c27214377ac7d75f4d2103e232b24c9353769321adbc51f5abc998258971fd27d42e07114d775623e3b4492103c403a9364dcb223cc32df5a4afab6089e941590cecfd5ac823c4fcff46e8f6c553aeb20c6d06000000001976a914b390187ef2854422ac5e4a2eb6ffe92496bef52388ac00000000"
Expand All @@ -102,10 +102,10 @@
"issuance": "01000000017fe100b9f1144c65ff6479f02def936a3eb3b897113edf57cec763ef0627a1fe000000001976a914b390187ef2854422ac5e4a2eb6ffe92496bef52388acffffffff02781e00000000000069512103ef16324526136068cea72482c101b243e5421a5f2b9266c2721437792fd75f822103e232b24c935376932a82bb53f0a9c8dc44fa029853d42e07114d775623e3b4d12103c403a9364dcb223cc32df5a4afab6089e941590cecfd5ac823c4fcff46e8f6c553aeb20c6d06000000001976a914b390187ef2854422ac5e4a2eb6ffe92496bef52388ac00000000"
},
{
"send": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff020000000000000000386a362a504df746f83442653dd7afa4dc727a030865749e9fba5aeb8fd21a9e68edbc79e78ed45723c1072c38aededa458f95fa2bdfdee082a343ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
"send": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff020000000000000000386a362a504df746f83442653dd7afa4dc727a030865749e9fba5aeb8fd21a9e68edbc79e78ed45723c1072c38aededa458f95fa2bdfdee0822d46ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
},
{
"send": "0100000001ebe3111881a8733ace02271dcf606b7450c41a48c1cb21fd73f4ba787b353ce4000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88acffffffff020000000000000000376a353ab408a679f108a19e35886a15c4c468ca75a06699f864a1ff235d087cbdc6ead3bcadef79a5333700c0c2401e15a313463096b9758fc5f505000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ac00000000"
"send": "0100000001ebe3111881a8733ace02271dcf606b7450c41a48c1cb21fd73f4ba787b353ce4000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88acffffffff020000000000000000376a353ab408a679f108a19e35886a15c4c468ca75a06699f864a1ff235d087cbdc6ead3bcadef79a5333700c0c2401e15a313463096b97532c8f505000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ac00000000"
},
{
"broadcast": "0100000001e80b32fd1670a1dc1c04ea50d944448fdd0f88b1bb1c127ee538d3b740d918c0000000001976a914c1a6de504b9bc0d0d6987312b2e37564079791b788acffffffff02781e00000000000069512102c6b33a609fc6c6aab6a34871732bf9e4e153dd640ea0fc40f5a57b897d6ef1db2103f1ad16418ba7228251a8e915fe8a380fa8dfcf29da2c89ee7bf0af43d6f276282102610f28a56e187f5cd133d7bfe107b159fa3b5129ba35e91fb915fe9a8efa43b453aeb20c6d06000000001976a914c1a6de504b9bc0d0d6987312b2e37564079791b788ac00000000"
Expand Down Expand Up @@ -141,9 +141,9 @@
"send": "01000000015ef833190e74ad47d8ae693f841a8b1b500ded7e23ee66b29898b72ec4914fdc010000001976a9144e5638a01efbb2f292481797ae1dcfcdaeb98d0088acffffffff0336150000000000001976a9146c39ee7c8f3a5ffa6121b0304a7a0de9d3d9a15288ac781e00000000000069512103685a00e94acebb82d5b591a4d755771c9cedf5125eb408e32319347fea7e3dda2103bc7b8d814ec2ece588d9da65aa9462c3f26ac0b0b5a719cd06de0aa258a1d953210378ee11c3fb97054877a809ce083db292b16d971bcdc6aa4c8f92087133729d8b53ae0027870b000000001976a9144e5638a01efbb2f292481797ae1dcfcdaeb98d0088ac00000000"
},
{
"issuance": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff020000000000000000356a332a504df746f83442653dd7b9a4dc727a09ac6c089e9fba5aeb8fd21af0e58754da540fb2663b79b6a2be04777ef0a3306526cea343ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
"issuance": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff020000000000000000356a332a504df746f83442653dd7b9a4dc727a09ac6c089e9fba5aeb8fd21af0e58754da540fb2663b79b6a2be04777ef0a3306526ce7846ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
},
{
"issuance": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff0200000000000000003f6a3d2a504df746f83442653dd7b8a58f7a5b641375109e9fba5aeb8fd21af0f509c47f29b52b01ff570ef34c933606b8812b7f2fde92e38b584cb8321cd593a343ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
"issuance": "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff0200000000000000003f6a3d2a504df746f83442653dd7b8a58f7a5b641375109e9fba5aeb8fd21af0f509c47f29b52b01ff570ef34c933606b8812b7f2fde92e38b584cb8321cd5937e45ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
}
]
Loading

0 comments on commit 03019e8

Please sign in to comment.