mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge branch 'master' into core/193/invalid-block-backlog
This commit is contained in:
commit
41328b3255
23
CHANGELOG.md
23
CHANGELOG.md
@ -14,6 +14,29 @@ For reference, the possible headings are:
|
||||
* **External Contributors** to list contributors outside of ascribe GmbH.
|
||||
|
||||
|
||||
## [0.3.0] - 2016-05-03
|
||||
Tag name: v0.3.0
|
||||
= commit:
|
||||
committed:
|
||||
|
||||
### Added
|
||||
- Crypto-conditions specs according to the Interledger protocol: [Pull Request #174](https://github.com/bigchaindb/bigchaindb/pull/174)
|
||||
- Added support for anonymous hashlocked conditions and fulfillments: [Pull Request #211](https://github.com/bigchaindb/bigchaindb/pull/211)
|
||||
|
||||
### Changed
|
||||
- Several improvements to the aws deployment scripts: [Pull Request #227](https://github.com/bigchaindb/bigchaindb/pull/227)
|
||||
|
||||
### Fixed
|
||||
- Bug related to block validation: [Pull Request #233](https://github.com/bigchaindb/bigchaindb/pull/233)
|
||||
|
||||
### Notes
|
||||
This release completely refactored the structure of the transactions and broke compatibility with older versions
|
||||
of BigchainDB. The refactor of the transactions was made in order to add support for multiple inputs/outputs and
|
||||
the crypto-conditions specs from the Interledger protocol.
|
||||
|
||||
We also updated the rethinkdb python drivers so you need to upgrade to rethinkdb v2.3+
|
||||
|
||||
|
||||
## [0.2.0] - 2016-04-26
|
||||
Tag name: v0.2.0
|
||||
= commit: 0c4a2b380aabdcf50fa2d7fb351c290aaedc3db7
|
||||
|
@ -43,6 +43,16 @@ my_string = 'This is a very long string, so long that it will not fit into just
|
||||
|
||||
It seems the preference is for slashes, but using parentheses is okay too. (There are good arguments either way. Arguing about it seems like a waste of time.)
|
||||
|
||||
### How to Format Long import Statements
|
||||
|
||||
If you need to `import` lots of names from a module or package, and they won't all fit in one line (without making the line too long), then use parentheses to spread the names across multiple lines, like so:
|
||||
```python
|
||||
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
|
||||
LEFT, DISABLED, NORMAL, RIDGE, END)
|
||||
```
|
||||
|
||||
For the rationale, see [PEP 328](https://www.python.org/dev/peps/pep-0328/#rationale-for-parentheses).
|
||||
|
||||
### Using the % operator or `format()` to Format Strings
|
||||
|
||||
Given the choice:
|
||||
|
@ -2,7 +2,7 @@
|
||||
[](https://pypi.python.org/pypi/BigchainDB)
|
||||
[](https://travis-ci.org/bigchaindb/bigchaindb)
|
||||
[](https://codecov.io/github/bigchaindb/bigchaindb?branch=master)
|
||||
[](https://bigchaindb.readthedocs.org/en/stable/)
|
||||
[](https://bigchaindb.readthedocs.org/en/latest/)
|
||||
|
||||
|
||||
# BigchainDB
|
||||
|
@ -176,7 +176,6 @@ class BaseConsensusRules(AbstractConsensusRules):
|
||||
|
||||
return transaction
|
||||
|
||||
# TODO: Unsure if a bigchain parameter is really necessary here?
|
||||
@staticmethod
|
||||
def validate_block(bigchain, block):
|
||||
"""Validate a block.
|
||||
@ -198,6 +197,15 @@ class BaseConsensusRules(AbstractConsensusRules):
|
||||
if calculated_hash != block['id']:
|
||||
raise exceptions.InvalidHash()
|
||||
|
||||
# Check if the block was created by a federation node
|
||||
if block['block']['node_pubkey'] not in (bigchain.federation_nodes + [bigchain.me]):
|
||||
raise exceptions.OperationError('Only federation nodes can create blocks')
|
||||
|
||||
# Check if block signature is valid
|
||||
verifying_key = crypto.VerifyingKey(block['block']['node_pubkey'])
|
||||
if not verifying_key.verify(util.serialize(block['block']), block['signature']):
|
||||
raise exceptions.InvalidSignature('Invalid block signature')
|
||||
|
||||
return block
|
||||
|
||||
@staticmethod
|
||||
|
@ -203,11 +203,20 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
},
|
||||
}
|
||||
"""
|
||||
# validate arguments (owners and inputs should be lists)
|
||||
# validate arguments (owners and inputs should be lists or None)
|
||||
|
||||
# The None case appears on fulfilling a hashlock
|
||||
if current_owners is None:
|
||||
current_owners = []
|
||||
if not isinstance(current_owners, list):
|
||||
current_owners = [current_owners]
|
||||
|
||||
# The None case appears on assigning a hashlock
|
||||
if new_owners is None:
|
||||
new_owners = []
|
||||
if not isinstance(new_owners, list):
|
||||
new_owners = [new_owners]
|
||||
|
||||
if not isinstance(inputs, list):
|
||||
inputs = [inputs]
|
||||
|
||||
@ -247,12 +256,22 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
# handle outputs
|
||||
conditions = []
|
||||
for fulfillment in fulfillments:
|
||||
|
||||
# threshold condition
|
||||
if len(new_owners) > 1:
|
||||
condition = cc.ThresholdSha256Fulfillment(threshold=len(new_owners))
|
||||
for new_owner in new_owners:
|
||||
condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=new_owner))
|
||||
|
||||
# simple signature condition
|
||||
elif len(new_owners) == 1:
|
||||
condition = cc.Ed25519Fulfillment(public_key=new_owners[0])
|
||||
|
||||
# to be added later (hashlock conditions)
|
||||
else:
|
||||
condition = None
|
||||
|
||||
if condition:
|
||||
conditions.append({
|
||||
'new_owners': new_owners,
|
||||
'condition': {
|
||||
|
@ -1,2 +1,2 @@
|
||||
__version__ = '0.2.0'
|
||||
__short_version__ = '0.2'
|
||||
__version__ = '0.3.0'
|
||||
__short_version__ = '0.3'
|
@ -26,6 +26,7 @@ coverage:
|
||||
- "deploy-cluster-aws/*"
|
||||
- "docs/*"
|
||||
- "tests/*"
|
||||
- "bigchaindb/version.py"
|
||||
|
||||
comment:
|
||||
# @stevepeak (from codecov.io) suggested we change 'suggestions' to 'uncovered'
|
||||
|
@ -746,3 +746,142 @@ threshold_tx_transfer
|
||||
"version":1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Hash-locked Conditions
|
||||
|
||||
By creating a hash of a difficult-to-guess 256-bit random or pseudo-random integer it is possible to create a condition which the creator can trivially fulfill by publishing the random value. However, for anyone else, the condition is cryptographically hard to fulfill, because they would have to find a preimage for the given condition hash.
|
||||
|
||||
One possible usecase might be to redeem a digital voucher when given a secret (voucher code).
|
||||
|
||||
```python
|
||||
# Create a hash-locked asset without any new_owners
|
||||
hashlock_tx = b.create_transaction(b.me, None, None, 'CREATE')
|
||||
|
||||
# Define a secret that will be hashed - fulfillments need to guess the secret
|
||||
secret = b'much secret! wow!'
|
||||
first_tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
|
||||
# The conditions list is empty, so we need to append a new condition
|
||||
hashlock_tx['transaction']['conditions'].append({
|
||||
'condition': {
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': 0,
|
||||
'new_owners': None
|
||||
})
|
||||
|
||||
# Conditions have been updated, so hash needs updating
|
||||
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)
|
||||
|
||||
# The asset needs to be signed by the current_owner
|
||||
hashlock_tx_signed = b.sign_transaction(hashlock_tx, b.me_private)
|
||||
|
||||
# Some validations
|
||||
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
|
||||
b.write_transaction(hashlock_tx_signed)
|
||||
hashlock_tx_signed
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"assignee":"FmLm6MxCABc8TsiZKdeYaZKo5yZWMM6Vty7Q1B6EgcP2",
|
||||
"id":"604c520244b7ff63604527baf269e0cbfb887122f503703120fd347d6b99a237",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"uri":"cc:0:3:nsW2IiYgk9EUtsg4uBe3pBnOgRoAEX2IIsPgjqZz47U:17"
|
||||
},
|
||||
"new_owners":None
|
||||
}
|
||||
],
|
||||
"data":None,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners":[
|
||||
"FmLm6MxCABc8TsiZKdeYaZKo5yZWMM6Vty7Q1B6EgcP2"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:21-D-LfNhIQhvY5914ArFTUGpgPKc7EVC1ZtJqqOTHGx1p9FuRr9tRfkbdqtX2MZWh7sRVUmMnwp7I1-xZbCnCkeADf69IwDHbZvNS6aTr1CpekREsV9ZG8m_wjlZiUN",
|
||||
"input":None
|
||||
}
|
||||
],
|
||||
"operation":"CREATE",
|
||||
"timestamp":"1461250387.910102"
|
||||
},
|
||||
"version":1
|
||||
}
|
||||
```
|
||||
|
||||
In order to redeem the asset, one needs to create a fulfillment the correct secret as a preimage:
|
||||
|
||||
```python
|
||||
hashlockuser_priv, hashlockuser_pub = crypto.generate_key_pair()
|
||||
|
||||
# create hashlock fulfillment tx
|
||||
hashlock_fulfill_tx = b.create_transaction(None, hashlockuser_pub, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER')
|
||||
|
||||
# provide a wrong secret
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=b'')
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == False
|
||||
|
||||
# provide the right secret
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
|
||||
b.write_transaction(hashlock_fulfill_tx)
|
||||
hashlock_fulfill_tx
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"assignee":"FmLm6MxCABc8TsiZKdeYaZKo5yZWMM6Vty7Q1B6EgcP2",
|
||||
"id":"fe6871bf3ca62eb61c52c5555cec2e07af51df817723f0cb76e5cf6248f449d2",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"EiqCKxnBCmmNb83qyGch48tULK9RLaEt4xFA43UVCVDb",
|
||||
"signature":None,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri":"cc:4:20:y9884Md2YI_wdnGSTJGhwvFaNsKLe8sqwimqk-2JLSI:96"
|
||||
},
|
||||
"new_owners":[
|
||||
"EiqCKxnBCmmNb83qyGch48tULK9RLaEt4xFA43UVCVDb"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":None,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners":[],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:0:bXVjaCBzZWNyZXQhIHdvdyE",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"604c520244b7ff63604527baf269e0cbfb887122f503703120fd347d6b99a237"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1461250397.944510"
|
||||
},
|
||||
"version":1
|
||||
}
|
||||
```
|
@ -433,6 +433,37 @@ class TestBlockValidation(object):
|
||||
assert block == b.validate_block(block)
|
||||
assert b.is_valid_block(block)
|
||||
|
||||
def test_invalid_signature(self, b):
|
||||
# create a valid block
|
||||
block = b.create_block([])
|
||||
|
||||
# replace the block signature with an invalid one
|
||||
block['signature'] = crypto.SigningKey(b.me_private).sign(b'wrongdata')
|
||||
|
||||
# check that validate_block raises an InvalidSignature exception
|
||||
with pytest.raises(exceptions.InvalidSignature):
|
||||
b.validate_block(block)
|
||||
|
||||
def test_invalid_node_pubkey(self, b):
|
||||
# blocks can only be created by a federation node
|
||||
# create a valid block
|
||||
block = b.create_block([])
|
||||
|
||||
# create some temp keys
|
||||
tmp_sk, tmp_vk = crypto.generate_key_pair()
|
||||
|
||||
# change the block node_pubkey
|
||||
block['block']['node_pubkey'] = tmp_vk
|
||||
|
||||
# just to make sure lets re-hash the block and create a valid signature
|
||||
# from a non federation node
|
||||
block['id'] = crypto.hash_data(util.serialize(block['block']))
|
||||
block['signature'] = crypto.SigningKey(tmp_sk).sign(util.serialize(block['block']))
|
||||
|
||||
# check that validate_block raises an OperationError
|
||||
with pytest.raises(exceptions.OperationError):
|
||||
b.validate_block(block)
|
||||
|
||||
|
||||
class TestBigchainVoter(object):
|
||||
def test_valid_block_voting(self, b):
|
||||
@ -1544,6 +1575,136 @@ class TestCryptoconditions(object):
|
||||
|
||||
assert b.verify_signature(tx_transfer_signed) is True
|
||||
|
||||
def test_create_asset_with_hashlock_condition(self, b):
|
||||
hashlock_tx = b.create_transaction(b.me, None, None, 'CREATE')
|
||||
|
||||
secret = b'much secret! wow!'
|
||||
first_tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
|
||||
hashlock_tx['transaction']['conditions'].append({
|
||||
'condition': {
|
||||
'details': json.loads(first_tx_condition.serialize_json()),
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': 0,
|
||||
'new_owners': None
|
||||
})
|
||||
# conditions have been updated, so hash needs updating
|
||||
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)
|
||||
|
||||
hashlock_tx_signed = b.sign_transaction(hashlock_tx, b.me_private)
|
||||
|
||||
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
|
||||
b.write_transaction(hashlock_tx_signed)
|
||||
|
||||
# create and write block to bigchain
|
||||
block = b.create_block([hashlock_tx_signed])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_transfer_asset_with_hashlock_condition(self, b, user_vk, user_sk):
|
||||
first_input_tx = b.get_owned_ids(user_vk).pop()
|
||||
|
||||
hashlock_tx = b.create_transaction(user_vk, None, first_input_tx, 'TRANSFER')
|
||||
|
||||
secret = b'much secret! wow!'
|
||||
first_tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
|
||||
hashlock_tx['transaction']['conditions'].append({
|
||||
'condition': {
|
||||
'details': json.loads(first_tx_condition.serialize_json()),
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': 0,
|
||||
'new_owners': None
|
||||
})
|
||||
# conditions have been updated, so hash needs updating
|
||||
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)
|
||||
|
||||
hashlock_tx_signed = b.sign_transaction(hashlock_tx, user_sk)
|
||||
|
||||
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert len(b.get_owned_ids(user_vk)) == 1
|
||||
|
||||
b.write_transaction(hashlock_tx_signed)
|
||||
|
||||
# create and write block to bigchain
|
||||
block = b.create_block([hashlock_tx_signed])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
assert len(b.get_owned_ids(user_vk)) == 0
|
||||
|
||||
def test_create_and_fulfill_asset_with_hashlock_condition(self, b, user_vk):
|
||||
hashlock_tx = b.create_transaction(b.me, None, None, 'CREATE')
|
||||
|
||||
secret = b'much secret! wow!'
|
||||
first_tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
|
||||
hashlock_tx['transaction']['conditions'].append({
|
||||
'condition': {
|
||||
'details': json.loads(first_tx_condition.serialize_json()),
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': 0,
|
||||
'new_owners': None
|
||||
})
|
||||
# conditions have been updated, so hash needs updating
|
||||
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)
|
||||
|
||||
hashlock_tx_signed = b.sign_transaction(hashlock_tx, b.me_private)
|
||||
|
||||
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
|
||||
b.write_transaction(hashlock_tx_signed)
|
||||
|
||||
# create and write block to bigchain
|
||||
block = b.create_block([hashlock_tx_signed])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
assert len(b.get_owned_ids(b.me)) == 0
|
||||
|
||||
# create hashlock fulfillment tx
|
||||
hashlock_fulfill_tx = b.create_transaction(None, user_vk, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER')
|
||||
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=b'')
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
with pytest.raises(exceptions.InvalidSignature):
|
||||
b.validate_transaction(hashlock_fulfill_tx)
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == False
|
||||
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
|
||||
b.write_transaction(hashlock_fulfill_tx)
|
||||
|
||||
# create and write block to bigchain
|
||||
block = b.create_block([hashlock_fulfill_tx])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
assert len(b.get_owned_ids(b.me)) == 0
|
||||
assert len(b.get_owned_ids(user_vk)) == 1
|
||||
|
||||
# try doublespending
|
||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
||||
hashlock_doublespend_tx = b.create_transaction(None, user2_vk, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER')
|
||||
|
||||
hashlock_doublespend_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
hashlock_doublespend_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_doublespend_tx_fulfillment.serialize_uri()
|
||||
|
||||
with pytest.raises(exceptions.DoubleSpend):
|
||||
b.validate_transaction(hashlock_doublespend_tx)
|
||||
|
||||
def test_get_subcondition_from_vk(self, b, user_sk, user_vk):
|
||||
user2_sk, user2_vk = crypto.generate_key_pair()
|
||||
user3_sk, user3_vk = crypto.generate_key_pair()
|
||||
|
@ -233,4 +233,60 @@ b.write_transaction(threshold_tx_transfer)
|
||||
|
||||
print(json.dumps(threshold_tx_transfer, sort_keys=True, indent=4, separators=(',', ':')))
|
||||
|
||||
"""
|
||||
Hashlocked Conditions
|
||||
"""
|
||||
|
||||
# Create a hash-locked asset without any new_owners
|
||||
hashlock_tx = b.create_transaction(b.me, None, None, 'CREATE')
|
||||
|
||||
# Define a secret that will be hashed - fulfillments need to guess the secret
|
||||
secret = b'much secret! wow!'
|
||||
first_tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
|
||||
# The conditions list is empty, so we need to append a new condition
|
||||
hashlock_tx['transaction']['conditions'].append({
|
||||
'condition': {
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
},
|
||||
'cid': 0,
|
||||
'new_owners': None
|
||||
})
|
||||
|
||||
# Conditions have been updated, so hash needs updating
|
||||
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)
|
||||
|
||||
# The asset needs to be signed by the current_owner
|
||||
hashlock_tx_signed = b.sign_transaction(hashlock_tx, b.me_private)
|
||||
|
||||
# Some validations
|
||||
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed
|
||||
|
||||
b.write_transaction(hashlock_tx_signed)
|
||||
print(json.dumps(hashlock_tx_signed, sort_keys=True, indent=4, separators=(',', ':')))
|
||||
|
||||
sleep(10)
|
||||
|
||||
hashlockuser_priv, hashlockuser_pub = crypto.generate_key_pair()
|
||||
|
||||
# create hashlock fulfillment tx
|
||||
hashlock_fulfill_tx = b.create_transaction(None, hashlockuser_priv, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER')
|
||||
|
||||
# try a wrong secret
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=b'')
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == False
|
||||
|
||||
# provide the right secret
|
||||
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=secret)
|
||||
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
|
||||
hashlock_fulfill_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
assert b.is_valid_transaction(hashlock_fulfill_tx) == hashlock_fulfill_tx
|
||||
|
||||
b.write_transaction(hashlock_fulfill_tx)
|
||||
print(json.dumps(hashlock_fulfill_tx, sort_keys=True, indent=4, separators=(',', ':')))
|
||||
|
Loading…
x
Reference in New Issue
Block a user