Skip to content

Commit

Permalink
start compose_presigned implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouziel committed Sep 4, 2024
1 parent 72260f6 commit 60dd831
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 12 deletions.
1 change: 1 addition & 0 deletions counterparty-core/counterpartycore/lib/api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"/v2/addresses/<address>/compose/fairminter": transaction.compose_fairminter,
"/v2/addresses/<address>/compose/fairmint": transaction.compose_fairmint,
"/v2/addresses/<address>/compose/attach": transaction.compose_attach,
"/v2/addresses/<address>/compose/presigned": transaction.compose_presigned,
"/v2/utxos/<utxo>/compose/detach": transaction.compose_detach,
"/v2/utxos/<utxo>/compose/movetoutxo": transaction.compose_movetoutxo,
"/v2/compose": transaction.compose_multiple,
Expand Down
54 changes: 53 additions & 1 deletion counterparty-core/counterpartycore/lib/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,8 @@ def compose_transaction(
return_only_data=False,
compose_data=None,
no_validate=False,
data_signer=None,
data_signature=None,
):
"""Create and return a transaction."""

Expand Down Expand Up @@ -1266,7 +1268,6 @@ def compose_transaction(

if compose_data is None:
tx_info = compose_method(db, **params)

if util.enabled("new_tx_format"):
# add flags and message length to the message
if tx_info[2]:
Expand All @@ -1275,6 +1276,12 @@ def compose_transaction(
message = flags + message_length + tx_info[2]
tx_info = (tx_info[0], tx_info[1], message)
else:
if util.enabled("new_tx_format") and data_signer and data_signature:
source_length = varint.encode(len(data_signer))
signature_length = varint.encode(len(data_signature))
compose_data = (
source_length + data_signer + signature_length + data_signature + compose_data
)
tx_info = compose_data

if return_only_data:
Expand Down Expand Up @@ -2162,6 +2169,51 @@ def compose_multiple(db, json_txs: str):
}


def compose_presigned(
db, address: str, inputs: str, data: str, signature: str, destination: str, btc_amount: int
):
"""
Composes a transaction from presigned inputs.
:param address: The signer of the data
:param inputs: The inputs to the transaction, first input is used to determine the source address
:param data: The data to include in the transaction
:param signature: The signature of the data
:param destination: The destination of the transaction
:param btc_amount: The amount of BTC to send
"""
custom_inputs = []
for input in inputs.split(","):

Check warning

Code scanning / pylint

Redefining built-in 'input'. Warning

Redefining built-in 'input'.
tx_hash, vout = input.split(":")
custom_inputs.append({"txid": tx_hash, "vout": int(vout)})

first_input_address = backend.bitcoind.safe_get_utxo_address(inputs[0])
if first_input_address is None:
raise exceptions.ComposeError(f"Invalid UTXO: {inputs[0]}")

rawtransaction = compose_transaction(
db,
name="",
params={},
custom_inputs=custom_inputs,
compose_data=(first_input_address, destination, data),
data_signature=signature,
data_signer=address,
)

return {
"rawtransaction": rawtransaction,
"params": {
"inputs": inputs,
"data": data,
"address": address,
"signature": signature,
"destination": destination,
"btc_amount": btc_amount,
},
"name": "presigned",
}


def info(db, rawtransaction: str, block_index: int = None):
"""
Returns Counterparty information from a raw transaction in hex format.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ def wait_for_bitcoind(self):
print("Waiting for bitcoind to start...")
time.sleep(1)

def send_transaction(self, source, tx_name, params, retry=0):
def send_transaction(self, source, tx_name, params, retry=0, return_only_data=False):
self.wait_for_counterparty_server()
if return_only_data:
params["return_only_data"] = 1
query_string = urllib.parse.urlencode(params)
if tx_name in ["detach", "movetoutxo"]:
compose_url = f"utxos/{source}/compose/{tx_name}?{query_string}"
Expand All @@ -63,6 +65,8 @@ def send_transaction(self, source, tx_name, params, retry=0):
if "error" in result:
raise ComposeError(result["error"])
raw_transaction = result["result"]["rawtransaction"]
if return_only_data:
return raw_transaction
# print(f"Raw transaction: {tx_name} {params} ({raw_transaction})")
signed_transaction_json = self.bitcoin_wallet(
"signrawtransactionwithwallet", raw_transaction
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
SCENARIO = [
{
"title": "Presigned send",
"transaction": "presigned_send",
"source": "$ADDRESS_1",
"signer": "$ADDRESS_2",
"params": {
"destination": "$ADDRESS_3",
"asset": "XCP",
"quantity": 100000,
},
"controls": [],
}
]
35 changes: 25 additions & 10 deletions counterparty-core/counterpartycore/test/regtest/testscenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
scenario_3_dispenser,
scenario_4_utxo,
scenario_5_chaining,
scenario_6_presigned,
)
from termcolor import colored

Expand All @@ -20,6 +21,8 @@
SCENARIOS += scenario_3_dispenser.SCENARIO
SCENARIOS += scenario_4_utxo.SCENARIO
SCENARIOS += scenario_5_chaining.SCENARIO
# SCENARIOS += scenario_6_presigned.SCENARIO
SCENARIOS = scenario_6_presigned.SCENARIO


def compare_strings(string1, string2):
Expand All @@ -31,23 +34,35 @@ def compare_strings(string1, string2):
return len(diff)


def prepare_item(item, node, context):
for i, address in enumerate(node.addresses):
item["source"] = item["source"].replace(f"$ADDRESS_{i+1}", address)
for key in item["params"]:
if isinstance(item["params"][key], str):
item["params"][key] = item["params"][key].replace(f"$ADDRESS_{i+1}", address)
for name, value in context.items():
item["source"] = item["source"].replace(f"${name}", value)
for key in item["params"]:
if isinstance(item["params"][key], str):
item["params"][key] = item["params"][key].replace(f"${name}", value)
return item


def run_item(node, item, context):
print(f"Running: {item['title']}")
if item["transaction"] == "mine_blocks":
block_hash, block_time = node.mine_blocks(item["params"]["blocks"])
tx_hash = "null"
node.wait_for_counterparty_server()
elif item["transaction"].startswith("presigned"):
item["transaction"] = item["transaction"].replace("presigned_", "")
item = prepare_item(item, node, context)
data = node.send_transaction(
item["source"], item["transaction"], item["params"], return_only_data=True
)
print(data)
else:
for i, address in enumerate(node.addresses):
item["source"] = item["source"].replace(f"$ADDRESS_{i+1}", address)
for key in item["params"]:
if isinstance(item["params"][key], str):
item["params"][key] = item["params"][key].replace(f"$ADDRESS_{i+1}", address)
for name, value in context.items():
item["source"] = item["source"].replace(f"${name}", value)
for key in item["params"]:
if isinstance(item["params"][key], str):
item["params"][key] = item["params"][key].replace(f"${name}", value)
item = prepare_item(item, node, context)
try:
tx_hash, block_hash, block_time = node.send_transaction(
item["source"], item["transaction"], item["params"]
Expand Down

0 comments on commit 60dd831

Please sign in to comment.