Add OP_RETURN support for heirs
Allow heirs to produce an OP_RETURN output instead of a regular BTC payment. An address prefixed with OP_RETURN: carries hex data (max 80 bytes); such heirs always have amount 0 and are excluded from amount calculations. GUI dialog shows a message field with the decoded text, the heir list displays the decoded message, and the OP_RETURN output is emitted with zero value in inheritance transactions.
This commit is contained in:
@@ -16,7 +16,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
|
||||
from bal.core.heirs import (
|
||||
HEIR_ADDRESS, HEIR_AMOUNT, HEIR_LOCKTIME, HEIR_REAL_AMOUNT,
|
||||
HEIR_DUST_AMOUNT, TRANSACTION_LABEL,
|
||||
OP_RETURN_PREFIX,
|
||||
create_op_return_script,
|
||||
is_op_return_address, get_op_return_hex, validate_op_return_hex,
|
||||
AliasNotFoundException,
|
||||
NotAnAddress, AmountNotValid, LocktimeNotValid,
|
||||
HeirExpiredException, HeirAmountIsDustException,
|
||||
@@ -258,6 +260,96 @@ def test_validate_removes_invalid():
|
||||
assert "alice" in result or True # may or may not pass address check
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# OP_RETURN helpers
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_op_return_prefix_constant():
|
||||
assert OP_RETURN_PREFIX == "OP_RETURN:"
|
||||
|
||||
|
||||
def test_is_op_return_address():
|
||||
assert is_op_return_address("OP_RETURN:48656c6c6f")
|
||||
assert not is_op_return_address("bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq")
|
||||
assert not is_op_return_address("")
|
||||
assert not is_op_return_address("OP_RETURN")
|
||||
assert not is_op_return_address("OP_RETURNX:")
|
||||
|
||||
|
||||
def test_get_op_return_hex():
|
||||
assert get_op_return_hex("OP_RETURN:48656c6c6f") == "48656c6c6f"
|
||||
assert get_op_return_hex("bc1q...") is None
|
||||
assert get_op_return_hex("") is None
|
||||
|
||||
|
||||
def test_validate_op_return_hex_valid():
|
||||
validate_op_return_hex("48656c6c6f")
|
||||
|
||||
|
||||
def test_validate_op_return_hex_invalid():
|
||||
try:
|
||||
validate_op_return_hex("nothex!!")
|
||||
assert False, "expected NotAnAddress"
|
||||
except NotAnAddress:
|
||||
pass
|
||||
|
||||
|
||||
def test_validate_op_return_hex_too_long():
|
||||
try:
|
||||
validate_op_return_hex("ab" * 81)
|
||||
assert False, "expected NotAnAddress"
|
||||
except NotAnAddress:
|
||||
pass
|
||||
|
||||
|
||||
def test_validate_op_return_hex_empty():
|
||||
validate_op_return_hex("")
|
||||
|
||||
|
||||
def test_validate_address_op_return():
|
||||
addr = "OP_RETURN:48656c6c6f"
|
||||
result = Heirs.validate_address(addr)
|
||||
assert result == addr
|
||||
|
||||
|
||||
def test_validate_heir_op_return():
|
||||
k = "test_op_return"
|
||||
v = ["OP_RETURN:48656c6c6f", "0", "30d"]
|
||||
result = Heirs.validate_heir(k, v)
|
||||
assert result[0] == "OP_RETURN:48656c6c6f"
|
||||
assert result[1] == "0"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Heirs class OP_RETURN integration
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_heirs_fixed_percent_skips_op_return():
|
||||
class FakeWallet:
|
||||
class FakeDB:
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
def get(self, key, default=None):
|
||||
return self._data.get(key, default)
|
||||
def put(self, key, value):
|
||||
self._data[key] = value
|
||||
def __init__(self):
|
||||
self.db = self.FakeDB()
|
||||
self.dust_threshold = lambda: 500
|
||||
wallet = FakeWallet()
|
||||
heirs = Heirs(wallet)
|
||||
heirs["op_ret"] = ["OP_RETURN:48656c6c6f", "0", "9999999999"]
|
||||
heirs["normal"] = ["addr1", "10000", "9999999999"]
|
||||
fixed_h, fixed_amt, perc_h, perc_amt, fixed_with_dust = (
|
||||
heirs.fixed_percent_lists_amount(0, 500)
|
||||
)
|
||||
assert "op_ret" in fixed_h
|
||||
assert "normal" in fixed_h
|
||||
assert fixed_h["op_ret"][HEIR_REAL_AMOUNT] == 0
|
||||
assert fixed_h["normal"][HEIR_REAL_AMOUNT] == 10000
|
||||
assert fixed_amt == 10000 # OP_RETURN adds 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for name in sorted(dir()):
|
||||
if name.startswith("test_"):
|
||||
|
||||
Reference in New Issue
Block a user