From bb88279b64461e9bf373f2d6691dce8dee9af172 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Mar 2016 10:49:39 +0100 Subject: [PATCH] fix: use _bitmask for seriallizing thresholdconditions --- bigchaindb/crypto/bitmark_registry.py | 4 ++-- bigchaindb/crypto/buffer.py | 8 ++++--- bigchaindb/crypto/crypto.md | 8 +++---- bigchaindb/crypto/fulfillment.py | 5 ++-- tests/crypto/test_fulfillment.py | 34 +++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/bigchaindb/crypto/bitmark_registry.py b/bigchaindb/crypto/bitmark_registry.py index 2f75b158..7ae345f7 100644 --- a/bigchaindb/crypto/bitmark_registry.py +++ b/bigchaindb/crypto/bitmark_registry.py @@ -1,4 +1,4 @@ -from bigchaindb.crypto.buffer import MAX_SAFE_INTEGER +from bigchaindb.crypto.buffer import MAX_SAFE_INTEGER_JS class BitmaskRegistry: @@ -18,7 +18,7 @@ class BitmaskRegistry: Class implementing the given fulfillment type. """ # Determine type of condition - if bitmask > MAX_SAFE_INTEGER: + if bitmask > MAX_SAFE_INTEGER_JS: raise ValueError('Bitmask {} is not supported'.format(bitmask)) for registered_type in BitmaskRegistry.registered_types: diff --git a/bigchaindb/crypto/buffer.py b/bigchaindb/crypto/buffer.py index 99a45b02..f3d641a6 100644 --- a/bigchaindb/crypto/buffer.py +++ b/bigchaindb/crypto/buffer.py @@ -12,7 +12,9 @@ MSBALL = ~REST INT = 2 ** 31 # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER -MAX_SAFE_INTEGER = 2 ** 53 - 1 +# we don't use sys.maxint (= 2 ** 63 - 1) as this spec is inline with the ILP JavaScript reference implementation +# see https://interledger.org/ +MAX_SAFE_INTEGER_JS = 2 ** 53 - 1 class UnsignedLEB128: @@ -24,7 +26,7 @@ class UnsignedLEB128: seven least significant bits of the number represented. see: https://en.wikipedia.org/wiki/LEB128 (ULEB128) - see http://grokbase.com/t/python/python-list/112e5jpc16/encoding + see: http://grokbase.com/t/python/python-list/112e5jpc16/encoding """ @@ -166,7 +168,7 @@ class Predictor: self.size += 1 elif val < 0: raise ValueError('Variable length integer cannot be negative') - elif val > MAX_SAFE_INTEGER: + elif val > MAX_SAFE_INTEGER_JS: raise ValueError('Variable length integer too large') else: # Calculate number of bits divided by seven diff --git a/bigchaindb/crypto/crypto.md b/bigchaindb/crypto/crypto.md index 300776ae..a2771234 100644 --- a/bigchaindb/crypto/crypto.md +++ b/bigchaindb/crypto/crypto.md @@ -1,7 +1,7 @@ # Crypto Conditions This spec is from the [**Interledger Protocol (ILP)**] -(https://github.com/interledger/five-bells-condition/tree/feature/binary-merkle-v2) +(https://interledger.org/five-bells-condition/spec.html) ## Motivation @@ -248,7 +248,7 @@ print(sha256fulfillment.validate() and \ RSA-SHA-256 is assigned the type bit 21 = 0x02. -**Warning:** not (yet) implemented in BigchainDB, for info see the [**ILP specification**](https://github.com/interledger/five-bells-condition/blob/feature/binary-merkle-v2/docs/spec.md) +**Warning:** not (yet) implemented in BigchainDB, for info see the [**ILP specification**](https://interledger.org/five-bells-condition/spec.html) ## ED25519-SHA-256 @@ -284,7 +284,7 @@ The `MESSAGE_ID` represents an identifier for the message. All messages in a cry The message to be signed is the concatenation of the `FIXED_PREFIX` and `DYNAMIC_MESSAGE`. -The `MESSAGE_ID`, `FIXED_PREFIX`, `DYNAMIC_MESSAGE_LENGTH` and `DYNAMIC_MESSAGE` fields have the same meaning as in the [**RSA-SHA-256 condition type**](https://github.com/interledger/five-bells-condition/blob/feature/binary-merkle-v2/docs/spec.md). +The `MESSAGE_ID`, `FIXED_PREFIX`, `DYNAMIC_MESSAGE_LENGTH` and `DYNAMIC_MESSAGE` fields have the same meaning as in the [**RSA-SHA-256 condition type**](https://interledger.org/five-bells-condition/spec.html). ### Usage @@ -297,7 +297,7 @@ sk = Ed25519SigningKey(b'9qLvREC54mhKYivr88VpckyVWdAFmifJpGjbvV5AiTRs') vk = sk.get_verifying_key() # Create an ED25519-SHA256 condition -ed25519_fulfillment = Ed25519Sha256Fulfillment() +ed25519_fulfill`nt = Ed25519Sha256Fulfillment() ed25519_fulfillment.public_key = vk ed25519_fulfillment.message_prefix = 'Hello world!' ed25519_fulfillment.max_dynamic_message_length = 32 # defaults to 0 diff --git a/bigchaindb/crypto/fulfillment.py b/bigchaindb/crypto/fulfillment.py index d43ade8c..5a00b33c 100644 --- a/bigchaindb/crypto/fulfillment.py +++ b/bigchaindb/crypto/fulfillment.py @@ -71,7 +71,8 @@ class Fulfillment(metaclass=ABCMeta): from bigchaindb.crypto.bitmark_registry import BitmaskRegistry - cls = BitmaskRegistry.get_class_from_typebit(reader.read_var_uint()) + cls_type = reader.read_var_uint() + cls = BitmaskRegistry.get_class_from_typebit(cls_type) fulfillment = cls() fulfillment.parse_payload(reader) @@ -151,7 +152,7 @@ class Fulfillment(metaclass=ABCMeta): Serialized fulfillment """ writer = Writer() - writer.write_var_uint(self.bitmask) + writer.write_var_uint(self._bitmask) self.write_payload(writer) return b''.join(writer.components) diff --git a/tests/crypto/test_fulfillment.py b/tests/crypto/test_fulfillment.py index 4e40ab88..383ca28b 100644 --- a/tests/crypto/test_fulfillment.py +++ b/tests/crypto/test_fulfillment.py @@ -292,3 +292,37 @@ class TestBigchainILPThresholdSha256Fulfillment: assert len(deserialized_fulfillment.get_all_subconditions()) == threshold assert deserialized_fulfillment.serialize_uri() == fulfillment_uri assert deserialized_fulfillment.validate() + + def test_fulfillment_nested_and_or(self): + ilp_fulfillment_sha = Fulfillment.from_uri(self.FULFILLMENT_SHA256_ILP) + ilp_fulfillment_ed1 = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP_2) + ilp_fulfillment_ed2 = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP) + + # 2-of-2 (AND with 2 inputs) + fulfillment = ThresholdSha256Fulfillment() + fulfillment.threshold = 2 + fulfillment.add_subfulfillment(ilp_fulfillment_sha) + + assert fulfillment.validate() is False + + # 1-of-2 (OR with 2 inputs) + nested_fulfillment = ThresholdSha256Fulfillment() + nested_fulfillment.threshold = 1 + nested_fulfillment.add_subfulfillment(ilp_fulfillment_ed1) + assert nested_fulfillment.validate() is True + nested_fulfillment.add_subfulfillment(ilp_fulfillment_ed2) + assert nested_fulfillment.validate() is True + + fulfillment.add_subfulfillment(nested_fulfillment) + assert fulfillment.validate() is True + + fulfillment_uri = fulfillment.serialize_uri() + deserialized_fulfillment = Fulfillment.from_uri(fulfillment_uri) + + assert isinstance(deserialized_fulfillment, ThresholdSha256Fulfillment) + assert deserialized_fulfillment.threshold == 2 + assert len(deserialized_fulfillment.subfulfillments) == 2 + assert len(deserialized_fulfillment.subfulfillments[1].subfulfillments) == 1 + assert len(deserialized_fulfillment.get_all_subconditions()) == 2 + assert deserialized_fulfillment.serialize_uri() == fulfillment_uri + assert deserialized_fulfillment.validate() \ No newline at end of file