-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path14_op_return.py
More file actions
49 lines (41 loc) · 2.15 KB
/
Copy path14_op_return.py
File metadata and controls
49 lines (41 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# SPDX-License-Identifier: MIT
"""14 - Write a short message onto the blockchain with an OP_RETURN output.
An OP_RETURN output carries up to about 80 bytes of arbitrary data and is provably
unspendable, so it never bloats the UTXO set. This uses your node's wallet to fund,
sign, and broadcast the transaction. The offline (no node) version is the JavaScript
recipe 14. The message is PUBLIC and PERMANENT, so never write anything private, on
testnet or anywhere. Read it back with recipe 10.
Fund your node's wallet first from cypherfaucet.com.
RPC_USER=... RPC_PASS=... python 14_op_return.py "your message"
"""
import sys
import requests
from config import RPC_URL, RPC_USER, RPC_PASS
def rpc(method, params=None):
payload = {"jsonrpc": "1.0", "id": "ex", "method": method, "params": params or []}
try:
r = requests.post(RPC_URL, json=payload, auth=(RPC_USER, RPC_PASS), timeout=30)
except requests.exceptions.RequestException:
raise SystemExit(f"could not reach your node at {RPC_URL}. is it running with RPC "
"enabled? see testnethub.com/run-node")
if r.status_code == 401:
raise SystemExit("the node rejected the login: set RPC_USER / RPC_PASS (see testnethub.com/rpc-safety)")
body = r.json()
if body.get("error"):
raise SystemExit(f"the node rejected the call: {body['error']['message']}")
return body["result"]
if len(sys.argv) < 2:
sys.exit('usage: python 14_op_return.py "your message"')
message = " ".join(sys.argv[1:])
data = message.encode("utf-8")
if len(data) > 80:
sys.exit(f"message is {len(data)} bytes; OP_RETURN is limited to about 80")
# A "data" output becomes an OP_RETURN carrying your bytes. The wallet then adds inputs
# and a change output, sets the fee, signs, and we broadcast the result.
raw = rpc("createrawtransaction", [[], [{"data": data.hex()}]])
funded = rpc("fundrawtransaction", [raw])["hex"]
signed = rpc("signrawtransactionwithwallet", [funded])["hex"]
txid = rpc("sendrawtransaction", [signed])
print(f"message : {message} ({len(data)} bytes)")
print(f"txid : {txid}")
print(f"read it : python 10_decode_tx.py {txid} (or open it on the explorer)")