Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve handling of spendable as a boolean #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions bip329/bip329_parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from .constants import VALID_SPENDABLE_VALUES
from .constants import BOOL_KEYS
from .constants import VALID_REQUIRED_KEYS
from .constants import VALID_TYPE_KEYS
from .constants import MANDATORY_KEYS_ERROR
Expand Down Expand Up @@ -33,17 +33,27 @@ def is_valid_entry(entry):
raise MANDATORY_KEYS_ERROR

if entry['type'] not in VALID_TYPE_KEYS:
# silently drop record types we don't understand
return False

if entry['type'] == 'output':
if 'spendable' in entry and entry['spendable'] not in VALID_SPENDABLE_VALUES:
return False
# cleanup booleans, which are poorly understood
for k in entry.keys():
if k in BOOL_KEYS:
v = entry[k]
if isinstance(v, str):
entry[k] = (v.lower() == 'true')
elif v is None:
entry[k] = False
else:
# handle 1/0 and correct bool JSON
entry[k] = bool(int(v))

if 'label' in entry and not isinstance(entry['label'], str):
return False
raise TypeError('label must be string')

if 'origin' in entry and not isinstance(entry['origin'], str):
# TODO: Verify origin
return False
raise TypeError('origin must be string')

# TODO: Verify origin

return True
24 changes: 9 additions & 15 deletions bip329/bip329_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import shutil
import time

from .constants import VALID_SPENDABLE_VALUES
from .constants import VALID_REQUIRED_KEYS
from .constants import VALID_TYPE_KEYS
from .constants import MANDATORY_KEYS_ERROR
Expand Down Expand Up @@ -80,22 +79,17 @@ def write_label(self, line):
"Invalid 'origin' field in BIP-329 record")

# Check and add "spendable" if present and valid
if callable(getattr(line, "spendable", None)):
spendable = line.spendable()
if spendable in VALID_SPENDABLE_VALUES:
label_dict["spendable"] = "true" if spendable in [
"true", True] else "false"
else:
raise ValueError(
"Invalid 'spendable' field in BIP-329 record")
elif "spendable" in line:
spendable = line["spendable"]
if spendable in VALID_SPENDABLE_VALUES:
label_dict["spendable"] = "true" if spendable in [
"true", True] else "false"
if ("spendable" in line) or hasattr(line, "spendable"):
if callable(getattr(line, "spendable", None)):
spendable = line.spendable()
else:
spendable = line["spendable"]

if spendable not in {True, False}:
raise ValueError(
"Invalid 'spendable' field in BIP-329 record")
"Invalid 'spendable' field in BIP-329 record: %r" % spendable)

label_dict["spendable"] = spendable

with open(self.filename, mode='a', encoding='utf-8') as writer:
writer.write(json.dumps(label_dict) + '\n')
Expand Down
3 changes: 2 additions & 1 deletion bip329/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

VALID_SPENDABLE_VALUES = (True, False, "true", "false")
VALID_REQUIRED_KEYS = ("type", "ref", "label")
VALID_TYPE_KEYS = ("tx", "addr", "pubkey", "input", "output", "xpub")

BOOL_KEYS = {"spendable", }

MANDATORY_KEYS_ERROR = ValueError(
"Mandatory keys 'type', 'ref', and 'label' are required in BIP-329 record")
2 changes: 1 addition & 1 deletion bip329/tests/test_bip329_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_load_entries(self):
"label": "Public Key"},
{"type": "input", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:0", "label": "Input"},
{"type": "output", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1",
"label": "Output", "spendable": "false"},
"label": "Output", "spendable": False},
{"type": "xpub", "ref": "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
"label": "Extended Public Key"},
{"type": "tx", "ref": "f546156d9044844e02b181026a1a407abfca62e7ea1159f87bbeaa77b4286c74",
Expand Down
4 changes: 3 additions & 1 deletion bip329/tests/test_bip329_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ def test_write_labels(self):
"label": "Public Key"},
{"type": "input", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:0", "label": "Input"},
{"type": "output", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1",
"label": "Output", "spendable": "false"},
"label": "Output", "spendable": False},
{"type": "output", "ref": "0000000078462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1",
"label": "Output", "spendable": True},
{"type": "xpub", "ref": "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
"label": "Extended Public Key"},
{"type": "tx", "ref": "f546156d9044844e02b181026a1a407abfca62e7ea1159f87bbeaa77b4286c74",
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='bip329',
version='0.0.3',
version='0.0.4',
packages=find_packages(),
install_requires=[
'py7zr',
Expand Down
2 changes: 1 addition & 1 deletion test-vectors.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
{ "type": "addr", "ref": "bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c", "label": "Address" }
{ "type": "pubkey", "ref": "0283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f448", "label": "Public Key" }
{ "type": "input", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:0", "label": "Input" }
{ "type": "output", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1", "label": "Output" , "spendable" : "false" }
{ "type": "output", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1", "label": "Output" , "spendable": false }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{ "type": "xpub", "ref": "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", "label": "Extended Public Key" }
{ "type": "tx", "ref": "f546156d9044844e02b181026a1a407abfca62e7ea1159f87bbeaa77b4286c74", "label": "Account #1 Transaction", "origin": "wpkh([d34db33f/84'/0'/1'])" }