mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
sha256 fulfillment
tests
This commit is contained in:
parent
821ca9f8e6
commit
9bd1e9ff8b
@ -51,8 +51,10 @@ class BitmaskRegistry:
|
||||
})
|
||||
|
||||
|
||||
from bigchaindb.crypto.fulfillments.sha256 import Sha256Fulfillment
|
||||
from bigchaindb.crypto.fulfillments.threshold_sha256 import ThresholdSha256Fulfillment
|
||||
from bigchaindb.crypto.fulfillments.ed25519_sha256 import Ed25519Sha256Fulfillment
|
||||
|
||||
BitmaskRegistry.register_type(Sha256Fulfillment)
|
||||
BitmaskRegistry.register_type(ThresholdSha256Fulfillment)
|
||||
BitmaskRegistry.register_type(Ed25519Sha256Fulfillment)
|
||||
|
||||
@ -5,7 +5,7 @@ from abc import ABCMeta, abstractmethod
|
||||
from six import string_types
|
||||
|
||||
from bigchaindb.crypto.condition import Condition
|
||||
from bigchaindb.crypto.iostream import Writer, base64_remove_padding, Reader, base64_add_padding
|
||||
from bigchaindb.crypto.iostream import Writer, base64_remove_padding, Reader, base64_add_padding, Predictor
|
||||
|
||||
FULFILLMENT_REGEX = r'^cf:1:[1-9a-f][0-9a-f]{0,2}:[a-zA-Z0-9_-]+$'
|
||||
|
||||
@ -179,9 +179,7 @@ class Fulfillment(metaclass=ABCMeta):
|
||||
Return:
|
||||
{Number} Maximum fulfillment length
|
||||
"""
|
||||
# TODO: Predictor
|
||||
# predictor = Predictor()
|
||||
predictor = None
|
||||
predictor = Predictor()
|
||||
self.write_payload(predictor)
|
||||
return predictor.size
|
||||
|
||||
|
||||
@ -164,6 +164,17 @@ class Ed25519Sha256Fulfillment(BaseSha256Fulfillment):
|
||||
|
||||
This writes the fulfillment payload to a Writer.
|
||||
|
||||
COMMON_HEADER =
|
||||
VARBYTES PUBLIC_KEY
|
||||
VARBYTES MESSAGE_ID
|
||||
VARBYTES FIXED_PREFIX
|
||||
VARUINT DYNAMIC_MESSAGE_LENGTH
|
||||
|
||||
FULFILLMENT_PAYLOAD =
|
||||
COMMON_HEADER
|
||||
VARBYTES DYNAMIC_MESSAGE
|
||||
VARBYTES SIGNATURE
|
||||
|
||||
Args:
|
||||
writer (Writer): Subject for writing the fulfillment payload.
|
||||
"""
|
||||
@ -178,6 +189,16 @@ class Ed25519Sha256Fulfillment(BaseSha256Fulfillment):
|
||||
|
||||
Writes the contents of the condition hash to a Hasher. Used internally by `condition`.
|
||||
|
||||
COMMON_HEADER =
|
||||
VARBYTES PUBLIC_KEY
|
||||
VARBYTES MESSAGE_ID
|
||||
VARBYTES FIXED_PREFIX
|
||||
VARUINT DYNAMIC_MESSAGE_LENGTH
|
||||
|
||||
HASH = SHA256(
|
||||
COMMON_HEADER
|
||||
)
|
||||
|
||||
Args:
|
||||
hasher (Hasher): Destination where the hash payload will be written.
|
||||
"""
|
||||
|
||||
94
bigchaindb/crypto/fulfillments/sha256.py
Normal file
94
bigchaindb/crypto/fulfillments/sha256.py
Normal file
@ -0,0 +1,94 @@
|
||||
from bigchaindb.crypto.fulfillments.base_sha256 import BaseSha256Fulfillment
|
||||
from bigchaindb.crypto.iostream import Hasher, Reader, Writer, Predictor
|
||||
|
||||
|
||||
class Sha256Fulfillment(BaseSha256Fulfillment):
|
||||
|
||||
_bitmask = 0x01
|
||||
|
||||
def __init__(self):
|
||||
self._preimage = None
|
||||
|
||||
@property
|
||||
def preimage(self):
|
||||
return self._preimage
|
||||
|
||||
@preimage.setter
|
||||
def preimage(self, value):
|
||||
"""
|
||||
Provide a preimage.
|
||||
|
||||
The preimage is the only input to a SHA256 hashlock condition.
|
||||
|
||||
Note that the preimage should contain enough (pseudo-random) data in order
|
||||
to be difficult to guess. A sufficiently large secret seed and a
|
||||
cryptographically secure pseudo-random number generator (CSPRNG) can be
|
||||
used to avoid having to store each individual preimage.
|
||||
|
||||
Args:
|
||||
value: Secret data that will be hashed to form the condition.
|
||||
"""
|
||||
# TODO: Verify preimage
|
||||
self._preimage = value
|
||||
|
||||
def write_hash_payload(self, hasher):
|
||||
"""
|
||||
Generate the contents of the condition hash.
|
||||
|
||||
Writes the contents of the condition hash to a Hasher. Used internally by `getCondition`.
|
||||
|
||||
HASH = SHA256(PREIMAGE)
|
||||
|
||||
Args:
|
||||
hasher (Hasher): Destination where the hash payload will be written.
|
||||
"""
|
||||
if not isinstance(hasher, Hasher):
|
||||
raise TypeError('hasher must be a Hasher instance')
|
||||
if self.preimage is None:
|
||||
raise ValueError('Could not calculate hash, no preimage provided')
|
||||
hasher.write(self.preimage)
|
||||
|
||||
def parse_payload(self, reader):
|
||||
"""
|
||||
Parse the payload of a SHA256 hashlock fulfillment.
|
||||
|
||||
Read a fulfillment payload from a Reader and populate this object with that fulfillment.
|
||||
|
||||
FULFILLMENT_PAYLOAD =
|
||||
VARBYTES PREIMAGE
|
||||
|
||||
Args:
|
||||
reader (Reader): Source to read the fulfillment payload from.
|
||||
"""
|
||||
if not isinstance(reader, Reader):
|
||||
raise TypeError('reader must be a Reader instance')
|
||||
self.preimage = reader.read_var_bytes()
|
||||
|
||||
def write_payload(self, writer):
|
||||
"""
|
||||
Generate the fulfillment payload.
|
||||
|
||||
This writes the fulfillment payload to a Writer.
|
||||
|
||||
Args:
|
||||
writer (Writer): Subject for writing the fulfillment payload.
|
||||
"""
|
||||
if not isinstance(writer, (Writer, Predictor)):
|
||||
raise TypeError('writer must be a Writer instance')
|
||||
if self.preimage is None:
|
||||
raise ValueError('Preimage must be specified')
|
||||
|
||||
writer.write_var_bytes(self.preimage)
|
||||
return writer
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Validate this fulfillment.
|
||||
|
||||
For a SHA256 hashlock fulfillment, successful parsing implies that the
|
||||
fulfillment is valid, so this method is a no-op.
|
||||
|
||||
Returns:
|
||||
boolean: Validation result
|
||||
"""
|
||||
return True
|
||||
@ -102,6 +102,14 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
|
||||
|
||||
This function is called internally by the `getCondition` method.
|
||||
|
||||
HASH = SHA256(
|
||||
VARUINT TYPE_BIT
|
||||
VARUINT THRESHOLD
|
||||
VARARRAY
|
||||
VARUINT WEIGHT
|
||||
CONDITION
|
||||
)
|
||||
|
||||
Args:
|
||||
hasher (Hasher): Hash generator
|
||||
"""
|
||||
@ -182,6 +190,15 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
|
||||
|
||||
This writes the fulfillment payload to a Writer.
|
||||
|
||||
FULFILLMENT_PAYLOAD =
|
||||
VARUINT THRESHOLD
|
||||
VARARRAY
|
||||
VARUINT WEIGHT
|
||||
FULFILLMENT
|
||||
VARARRAY
|
||||
VARUINT WEIGHT
|
||||
CONDITION
|
||||
|
||||
Args:
|
||||
writer (Writer): Subject for writing the fulfillment payload.
|
||||
"""
|
||||
@ -195,6 +212,7 @@ class ThresholdSha256Fulfillment(BaseSha256Fulfillment):
|
||||
# Prefer shorter fulfillments
|
||||
fulfillments.sort(key=lambda f: len(f['binary']))
|
||||
|
||||
# Cut off unnecessary fulfillments
|
||||
if len(fulfillments) < self.threshold:
|
||||
raise ValueError('Not enough subfulfillments')
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ from bigchaindb.crypto.condition import Condition
|
||||
from bigchaindb.crypto.ed25519 import ED25519PrivateKey, ED25519PublicKey
|
||||
from bigchaindb.crypto.fulfillment import Fulfillment
|
||||
from bigchaindb.crypto.fulfillments.ed25519_sha256 import Ed25519Sha256Fulfillment
|
||||
from bigchaindb.crypto.fulfillments.sha256 import Sha256Fulfillment
|
||||
from bigchaindb.crypto.fulfillments.threshold_sha256 import ThresholdSha256Fulfillment
|
||||
|
||||
|
||||
@ -20,6 +21,38 @@ class TestBigchainILPSha256Condition:
|
||||
assert condition.serialize_uri() == self.CONDITION_SHA256_ILP
|
||||
|
||||
|
||||
class TestBigchainILPSha256Fulfillment:
|
||||
CONDITION_SHA256_ILP = 'cc:1:1:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:1'
|
||||
FULFILLMENT_SHA256_ILP = 'cf:1:1:AA'
|
||||
|
||||
def test_deserialize_and_validate_fulfillment(self):
|
||||
fulfillment = Fulfillment.from_uri(self.FULFILLMENT_SHA256_ILP)
|
||||
assert fulfillment.serialize_uri() == self.FULFILLMENT_SHA256_ILP
|
||||
assert fulfillment.condition.serialize_uri() == self.CONDITION_SHA256_ILP
|
||||
assert fulfillment.validate()
|
||||
|
||||
def test_deserialize_condition_and_validate_fulfillment(self):
|
||||
condition = Condition.from_uri(self.CONDITION_SHA256_ILP)
|
||||
fulfillment = Sha256Fulfillment()
|
||||
fulfillment.preimage = ''
|
||||
assert fulfillment.serialize_uri() == self.FULFILLMENT_SHA256_ILP
|
||||
assert fulfillment.condition.serialize_uri() == condition.serialize_uri()
|
||||
assert fulfillment.validate()
|
||||
|
||||
def test_condition_from_fulfillment(self):
|
||||
fulfillment = Sha256Fulfillment()
|
||||
with pytest.raises(ValueError):
|
||||
fulfillment.condition
|
||||
|
||||
fulfillment.preimage = 'Hello World!'
|
||||
condition = fulfillment.condition
|
||||
|
||||
verify_fulfillment = Sha256Fulfillment()
|
||||
verify_fulfillment.preimage = 'Hello World!'
|
||||
assert verify_fulfillment.condition.serialize_uri() == condition.serialize_uri()
|
||||
assert verify_fulfillment.validate()
|
||||
|
||||
|
||||
class TestBigchainILPEd25519Sha256Fulfillment:
|
||||
PUBLIC_HEX_ILP = b'ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf'
|
||||
PUBLIC_B64_ILP = b'7Bcrk61eVjv0kyxw4SRQNMNUZ+8u/U1k6/gZaDRn4r8'
|
||||
@ -133,12 +166,14 @@ class TestBigchainILPThresholdSha256Fulfillment:
|
||||
'mUhQNmD2Cvk7e3EFOo-arA2TKYTP-474Z4okhbYmKij6XxObIbRsDScjXILAJ6mV5hP7Xyqkg5fcSsZbfRYypzlsAM'
|
||||
HASH_ED25519_HEX_ILP = b'a9020d5b6ba6e7d0b80c1f494955c7d6282a026698186aabca59475200a97cf5'
|
||||
|
||||
CONDITION_THRESHOLD_ED25519_ILP_2 = 'cc:1:c:IZgoTeE1Weg6tfGMLWGe2JmS-waBN-CUrlbhtI9GBcQ:230'
|
||||
CONDITION_SHA256_ILP = 'cc:1:1:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU:1'
|
||||
FULFILLMENT_SHA256_ILP = 'cf:1:1:AA'
|
||||
|
||||
CONDITION_THRESHOLD_ED25519_ILP_2 = 'cc:1:d:fDM51fekeLlbeF9yj9W1KT76jtqa7u0vMlJAbM4EyiE:230'
|
||||
FULFILLMENT_THRESHOLD_ED25519_ILP_2 = \
|
||||
'cf:1:4:AgIBCCDsFyuTrV5WO_STLHDhJFA0w1Rn7y79TWTr-BloNGfivwxIZWxsbyB3b3JsZCEgFSBDb25kaXRpb25zIGFyZSBoZXJlIUBDW' \
|
||||
'6ped9T2wiZUVLyoz-epNFyiTDqyBqNheurnrk7UZ2KyQdrdmbbXX1zOIMw__O3h9Z2U6buK05AMfNYUnacCAQgg7Bcrk61eVjv0kyxw4SRQN' \
|
||||
'MNUZ-8u_U1k6_gZaDRn4r8MSGVsbG8gd29ybGQhIBUgQ29uZGl0aW9ucyBhcmUgaGVyZSFAQ1uqXnfU9sImVFS8qM_nqTRcokw6sgajYXrq5' \
|
||||
'65O1GdiskHa3Zm2119cziDMP_zt4fWdlOm7itOQDHzWFJ2nAgEBCCD9bNOse8We_gj4fRwApZnpDeDdjQO7dpbTWcixoCyKj3Q'
|
||||
'cf:1:4:AgIBAQABCCDsFyuTrV5WO_STLHDhJFA0w1Rn7y79TWTr-BloNGfivwxIZWxsbyB3b3JsZCEgFSBDb25kaXRpb25zIGFyZSBoZXJlI' \
|
||||
'UBDW6ped9T2wiZUVLyoz-epNFyiTDqyBqNheurnrk7UZ2KyQdrdmbbXX1zOIMw__O3h9Z2U6buK05AMfNYUnacCAQEIIP1s06x7xZ7-CPh9H' \
|
||||
'AClmekN4N2NA7t2ltNZyLGgLIqPdA'
|
||||
|
||||
def create_fulfillment_ed25519sha256(self):
|
||||
sk = ED25519PrivateKey(self.PRIVATE_B58_ILP)
|
||||
@ -153,8 +188,9 @@ class TestBigchainILPThresholdSha256Fulfillment:
|
||||
return fulfillment
|
||||
|
||||
def test_serialize_condition_and_validate_fulfillment(self):
|
||||
ilp_fulfillment = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP)
|
||||
ilp_fulfillment_2 = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP_2)
|
||||
ilp_fulfillment = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP_2)
|
||||
ilp_fulfillment_2 = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP)
|
||||
ilp_fulfillment_3 = Fulfillment.from_uri(self.FULFILLMENT_SHA256_ILP)
|
||||
|
||||
assert ilp_fulfillment.validate() == True
|
||||
assert ilp_fulfillment_2.validate() == True
|
||||
@ -163,9 +199,9 @@ class TestBigchainILPThresholdSha256Fulfillment:
|
||||
|
||||
# Create a threshold condition
|
||||
fulfillment = ThresholdSha256Fulfillment()
|
||||
fulfillment.add_subfulfillment(ilp_fulfillment)
|
||||
fulfillment.add_subfulfillment(ilp_fulfillment_2)
|
||||
fulfillment.add_subfulfillment(ilp_fulfillment)
|
||||
fulfillment.add_subfulfillment(ilp_fulfillment)
|
||||
fulfillment.add_subfulfillment(ilp_fulfillment_3)
|
||||
fulfillment.threshold = THRESHOLD # defaults to subconditions.length
|
||||
|
||||
assert fulfillment.condition.serialize_uri() == self.CONDITION_THRESHOLD_ED25519_ILP_2
|
||||
@ -185,6 +221,10 @@ class TestBigchainILPThresholdSha256Fulfillment:
|
||||
assert len(fulfillment.get_all_subconditions()) == NUM_FULFILLMENTS
|
||||
assert fulfillment.serialize_uri() == self.FULFILLMENT_THRESHOLD_ED25519_ILP_2
|
||||
assert fulfillment.validate()
|
||||
assert isinstance(fulfillment.subfulfillments[0], Sha256Fulfillment)
|
||||
assert isinstance(fulfillment.subfulfillments[1], Ed25519Sha256Fulfillment)
|
||||
assert fulfillment.subfulfillments[0].condition.serialize_uri() == self.CONDITION_SHA256_ILP
|
||||
assert fulfillment.subfulfillments[1].condition.serialize_uri() == self.CONDITION_ED25519_ILP
|
||||
|
||||
def test_serialize_deserialize_fulfillment(self):
|
||||
ilp_fulfillment = Fulfillment.from_uri(self.FULFILLMENT_ED25519_ILP)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user