mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
492 lines
18 KiB
Python
492 lines
18 KiB
Python
import json
|
|
from time import sleep
|
|
|
|
import cryptoconditions as cc
|
|
|
|
from bigchaindb import Bigchain, util, crypto, exceptions
|
|
|
|
|
|
b = Bigchain()
|
|
|
|
"""
|
|
Create a Digital Asset
|
|
"""
|
|
|
|
# create a test user
|
|
testuser1_priv, testuser1_pub = crypto.generate_key_pair()
|
|
|
|
# define a digital asset data payload
|
|
digital_asset_payload = {'msg': 'Hello BigchainDB!'}
|
|
|
|
# a create transaction uses the operation `CREATE` and has no inputs
|
|
tx = b.create_transaction(b.me, testuser1_pub, None, 'CREATE', payload=digital_asset_payload)
|
|
|
|
# all transactions need to be signed by the user creating the transaction
|
|
tx_signed = b.sign_transaction(tx, b.me_private)
|
|
|
|
# write the transaction to the bigchain
|
|
# the transaction will be stored in a backlog where it will be validated,
|
|
# included in a block, and written to the bigchain
|
|
b.write_transaction(tx_signed)
|
|
|
|
sleep(8)
|
|
|
|
"""
|
|
Read the Creation Transaction from the DB
|
|
"""
|
|
|
|
tx_retrieved = b.get_transaction(tx_signed['id'])
|
|
|
|
print(json.dumps(tx_retrieved, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
print(testuser1_pub)
|
|
print(b.me)
|
|
|
|
print(tx_retrieved['id'])
|
|
|
|
"""
|
|
Transfer the Digital Asset
|
|
"""
|
|
|
|
# create a second testuser
|
|
testuser2_priv, testuser2_pub = crypto.generate_key_pair()
|
|
|
|
# retrieve the transaction with condition id
|
|
tx_retrieved_id = b.get_owned_ids(testuser1_pub).pop()
|
|
print(json.dumps(tx_retrieved_id, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
# create a transfer transaction
|
|
tx_transfer = b.create_transaction(testuser1_pub, testuser2_pub, tx_retrieved_id, 'TRANSFER')
|
|
|
|
# sign the transaction
|
|
tx_transfer_signed = b.sign_transaction(tx_transfer, testuser1_priv)
|
|
|
|
|
|
b.validate_transaction(tx_transfer_signed)
|
|
# write the transaction
|
|
b.write_transaction(tx_transfer_signed)
|
|
|
|
sleep(8)
|
|
|
|
# check if the transaction is already in the bigchain
|
|
tx_transfer_retrieved = b.get_transaction(tx_transfer_signed['id'])
|
|
print(json.dumps(tx_transfer_retrieved, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
"""
|
|
Double Spends
|
|
"""
|
|
|
|
# create another transfer transaction with the same input
|
|
tx_transfer2 = b.create_transaction(testuser1_pub, testuser2_pub, tx_retrieved_id, 'TRANSFER')
|
|
|
|
# sign the transaction
|
|
tx_transfer_signed2 = b.sign_transaction(tx_transfer2, testuser1_priv)
|
|
|
|
# check if the transaction is valid
|
|
try:
|
|
b.validate_transaction(tx_transfer_signed2)
|
|
except exceptions.DoubleSpend as e:
|
|
print(e)
|
|
|
|
"""
|
|
Multiple Owners
|
|
"""
|
|
|
|
# Create a new asset and assign it to multiple owners
|
|
tx_multisig = b.create_transaction(b.me, [testuser1_pub, testuser2_pub], None, 'CREATE')
|
|
|
|
# Have the federation sign the transaction
|
|
tx_multisig_signed = b.sign_transaction(tx_multisig, b.me_private)
|
|
|
|
b.validate_transaction(tx_multisig_signed)
|
|
b.write_transaction(tx_multisig_signed)
|
|
|
|
# wait a few seconds for the asset to appear on the blockchain
|
|
sleep(8)
|
|
|
|
# retrieve the transaction
|
|
tx_multisig_retrieved = b.get_transaction(tx_multisig_signed['id'])
|
|
assert tx_multisig_retrieved is not None
|
|
|
|
print(json.dumps(tx_multisig_retrieved, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
testuser3_priv, testuser3_pub = crypto.generate_key_pair()
|
|
|
|
tx_multisig_retrieved_id = b.get_owned_ids(testuser2_pub).pop()
|
|
tx_multisig_transfer = b.create_transaction([testuser1_pub, testuser2_pub], testuser3_pub, tx_multisig_retrieved_id, 'TRANSFER')
|
|
tx_multisig_transfer_signed = b.sign_transaction(tx_multisig_transfer, [testuser1_priv, testuser2_priv])
|
|
|
|
try:
|
|
b.validate_transaction(tx_multisig_transfer_signed)
|
|
except exceptions.InvalidSignature:
|
|
# import ipdb; ipdb.set_trace()
|
|
b.validate_transaction(tx_multisig_transfer_signed)
|
|
b.write_transaction(tx_multisig_transfer_signed)
|
|
|
|
# wait a few seconds for the asset to appear on the blockchain
|
|
sleep(8)
|
|
|
|
# retrieve the transaction
|
|
tx_multisig_transfer_retrieved = b.get_transaction(tx_multisig_transfer_signed['id'])
|
|
assert tx_multisig_transfer_retrieved is not None
|
|
print(json.dumps(tx_multisig_transfer_retrieved, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
"""
|
|
Multiple Inputs and Outputs
|
|
"""
|
|
for i in range(3):
|
|
tx_mimo_asset = b.create_transaction(b.me, testuser1_pub, None, 'CREATE')
|
|
tx_mimo_asset_signed = b.sign_transaction(tx_mimo_asset, b.me_private)
|
|
b.validate_transaction(tx_mimo_asset_signed)
|
|
b.write_transaction(tx_mimo_asset_signed)
|
|
|
|
sleep(8)
|
|
|
|
# get inputs
|
|
owned_mimo_inputs = b.get_owned_ids(testuser1_pub)
|
|
print(len(owned_mimo_inputs))
|
|
|
|
# create a transaction
|
|
tx_mimo = b.create_transaction(testuser1_pub, testuser2_pub, owned_mimo_inputs, 'TRANSFER')
|
|
|
|
tx_mimo_signed = b.sign_transaction(tx_mimo, testuser1_priv)
|
|
# write the transaction
|
|
b.validate_transaction(tx_mimo_signed)
|
|
b.write_transaction(tx_mimo_signed)
|
|
|
|
print(json.dumps(tx_mimo_signed, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
sleep(8)
|
|
|
|
"""
|
|
Threshold Conditions
|
|
"""
|
|
|
|
# create some new testusers
|
|
thresholduser1_priv, thresholduser1_pub = crypto.generate_key_pair()
|
|
thresholduser2_priv, thresholduser2_pub = crypto.generate_key_pair()
|
|
thresholduser3_priv, thresholduser3_pub = crypto.generate_key_pair()
|
|
|
|
# retrieve the last transaction of testuser2
|
|
tx_retrieved_id = b.get_owned_ids(testuser2_pub).pop()
|
|
|
|
# create a base template for a 1-input/3-output transaction
|
|
threshold_tx = b.create_transaction(testuser2_pub, [thresholduser1_pub, thresholduser2_pub, thresholduser3_pub],
|
|
tx_retrieved_id, 'TRANSFER')
|
|
|
|
# create a 2-out-of-3 Threshold Cryptocondition
|
|
threshold_condition = cc.ThresholdSha256Fulfillment(threshold=2)
|
|
threshold_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=thresholduser1_pub))
|
|
threshold_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=thresholduser2_pub))
|
|
threshold_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=thresholduser3_pub))
|
|
|
|
# update the condition in the newly created transaction
|
|
threshold_tx['transaction']['conditions'][0]['condition'] = {
|
|
'details': threshold_condition.to_dict(),
|
|
'uri': threshold_condition.condition.serialize_uri()
|
|
}
|
|
|
|
# conditions have been updated, so hash needs updating
|
|
threshold_tx['id'] = util.get_hash_data(threshold_tx)
|
|
|
|
# sign the transaction
|
|
threshold_tx_signed = b.sign_transaction(threshold_tx, testuser2_priv)
|
|
|
|
b.validate_transaction(threshold_tx_signed)
|
|
# write the transaction
|
|
b.write_transaction(threshold_tx_signed)
|
|
|
|
sleep(8)
|
|
|
|
# check if the transaction is already in the bigchain
|
|
tx_threshold_retrieved = b.get_transaction(threshold_tx_signed['id'])
|
|
print(json.dumps(tx_threshold_retrieved, sort_keys=True, indent=4, separators=(',', ':')))
|
|
|
|
thresholduser4_priv, thresholduser4_pub = crypto.generate_key_pair()
|
|
|
|
# retrieve the last transaction of thresholduser1_pub
|
|
tx_retrieved_id = b.get_owned_ids(thresholduser1_pub).pop()
|
|
|
|
# create a base template for a 2-input/1-output transaction
|
|
threshold_tx_transfer = b.create_transaction([thresholduser1_pub, thresholduser2_pub, thresholduser3_pub],
|
|
thresholduser4_pub, tx_retrieved_id, 'TRANSFER')
|
|
|
|
# parse the threshold cryptocondition
|
|
threshold_fulfillment = cc.Fulfillment.from_dict(threshold_tx['transaction']['conditions'][0]['condition']['details'])
|
|
|
|
subfulfillment1 = threshold_fulfillment.get_subcondition_from_vk(thresholduser1_pub)[0]
|
|
subfulfillment2 = threshold_fulfillment.get_subcondition_from_vk(thresholduser2_pub)[0]
|
|
subfulfillment3 = threshold_fulfillment.get_subcondition_from_vk(thresholduser3_pub)[0]
|
|
|
|
|
|
# get the fulfillment message to sign
|
|
threshold_tx_fulfillment_message = util.get_fulfillment_message(threshold_tx_transfer,
|
|
threshold_tx_transfer['transaction']['fulfillments'][0],
|
|
serialized=True)
|
|
|
|
# clear the subconditions of the threshold fulfillment, they will be added again after signing
|
|
threshold_fulfillment.subconditions = []
|
|
|
|
# sign and add the subconditions until threshold of 2 is reached
|
|
subfulfillment1.sign(threshold_tx_fulfillment_message, crypto.SigningKey(thresholduser1_priv))
|
|
threshold_fulfillment.add_subfulfillment(subfulfillment1)
|
|
subfulfillment2.sign(threshold_tx_fulfillment_message, crypto.SigningKey(thresholduser2_priv))
|
|
threshold_fulfillment.add_subfulfillment(subfulfillment2)
|
|
|
|
# Add remaining (unfulfilled) fulfillment as a condition
|
|
threshold_fulfillment.add_subcondition(subfulfillment3.condition)
|
|
|
|
assert threshold_fulfillment.validate(threshold_tx_fulfillment_message) == True
|
|
|
|
threshold_tx_transfer['transaction']['fulfillments'][0]['fulfillment'] = threshold_fulfillment.serialize_uri()
|
|
|
|
assert b.validate_fulfillments(threshold_tx_transfer) == True
|
|
|
|
assert b.validate_transaction(threshold_tx_transfer) == threshold_tx_transfer
|
|
|
|
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(8)
|
|
|
|
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=(',', ':')))
|
|
|
|
|
|
"""
|
|
Timeout Conditions
|
|
"""
|
|
# Create transaction template
|
|
tx_timeout = b.create_transaction(b.me, None, None, 'CREATE')
|
|
|
|
# Set expiry time (12 secs from now)
|
|
time_sleep = 12
|
|
time_expire = str(float(util.timestamp()) + time_sleep)
|
|
|
|
# only valid if the server time <= time_expire
|
|
condition_timeout = cc.TimeoutFulfillment(expire_time=time_expire)
|
|
|
|
# The conditions list is empty, so we need to append a new condition
|
|
tx_timeout['transaction']['conditions'].append({
|
|
'condition': {
|
|
'details': condition_timeout.to_dict(),
|
|
'uri': condition_timeout.condition.serialize_uri()
|
|
},
|
|
'cid': 0,
|
|
'new_owners': None
|
|
})
|
|
|
|
# conditions have been updated, so hash needs updating
|
|
tx_timeout['id'] = util.get_hash_data(tx_timeout)
|
|
|
|
# sign transaction
|
|
tx_timeout_signed = b.sign_transaction(tx_timeout, b.me_private)
|
|
|
|
b.write_transaction(tx_timeout_signed)
|
|
print(json.dumps(tx_timeout, sort_keys=True, indent=4, separators=(',', ':')))
|
|
sleep(8)
|
|
|
|
# Retrieve the transaction id of tx_timeout
|
|
tx_timeout_id = {'txid': tx_timeout['id'], 'cid': 0}
|
|
|
|
# Create a template to transfer the tx_timeout
|
|
tx_timeout_transfer = b.create_transaction(None, testuser1_pub, tx_timeout_id, 'TRANSFER')
|
|
|
|
# Parse the threshold cryptocondition
|
|
timeout_fulfillment = cc.Fulfillment.from_dict(
|
|
tx_timeout['transaction']['conditions'][0]['condition']['details'])
|
|
|
|
tx_timeout_transfer['transaction']['fulfillments'][0]['fulfillment'] = timeout_fulfillment.serialize_uri()
|
|
|
|
# no need to sign transaction, like with hashlocks
|
|
for i in range(time_sleep - 4):
|
|
tx_timeout_valid = b.is_valid_transaction(tx_timeout_transfer) == tx_timeout_transfer
|
|
seconds_to_timeout = int(float(time_expire) - float(util.timestamp()))
|
|
print('tx_timeout valid: {} ({}s to timeout)'.format(tx_timeout_valid, seconds_to_timeout))
|
|
sleep(1)
|
|
|
|
"""
|
|
Escrow Conditions
|
|
"""
|
|
# retrieve the last transaction of testuser2
|
|
tx_retrieved_id = b.get_owned_ids(testuser2_pub).pop()
|
|
|
|
# Create escrow template with the execute and abort address
|
|
tx_escrow = b.create_transaction(testuser2_pub, [testuser2_pub, testuser1_pub], tx_retrieved_id, 'TRANSFER')
|
|
|
|
# Set expiry time (12 secs from now)
|
|
time_sleep = 12
|
|
time_expire = str(float(util.timestamp()) + time_sleep)
|
|
|
|
# Create escrow and timeout condition
|
|
condition_escrow = cc.ThresholdSha256Fulfillment(threshold=1) # OR Gate
|
|
condition_timeout = cc.TimeoutFulfillment(expire_time=time_expire) # only valid if now() <= time_expire
|
|
condition_timeout_inverted = cc.InvertedThresholdSha256Fulfillment(threshold=1)
|
|
condition_timeout_inverted.add_subfulfillment(condition_timeout)
|
|
|
|
# Create execute branch
|
|
condition_execute = cc.ThresholdSha256Fulfillment(threshold=2) # AND gate
|
|
condition_execute.add_subfulfillment(cc.Ed25519Fulfillment(public_key=testuser1_pub)) # execute address
|
|
condition_execute.add_subfulfillment(condition_timeout) # federation checks on expiry
|
|
condition_escrow.add_subfulfillment(condition_execute)
|
|
|
|
# Create abort branch
|
|
condition_abort = cc.ThresholdSha256Fulfillment(threshold=2) # AND gate
|
|
condition_abort.add_subfulfillment(cc.Ed25519Fulfillment(public_key=testuser2_pub)) # abort address
|
|
condition_abort.add_subfulfillment(condition_timeout_inverted)
|
|
condition_escrow.add_subfulfillment(condition_abort)
|
|
|
|
# Update the condition in the newly created transaction
|
|
tx_escrow['transaction']['conditions'][0]['condition'] = {
|
|
'details': condition_escrow.to_dict(),
|
|
'uri': condition_escrow.condition.serialize_uri()
|
|
}
|
|
|
|
# conditions have been updated, so hash needs updating
|
|
tx_escrow['id'] = util.get_hash_data(tx_escrow)
|
|
|
|
# sign transaction
|
|
tx_escrow_signed = b.sign_transaction(tx_escrow, testuser2_priv)
|
|
|
|
# some checks
|
|
assert b.validate_transaction(tx_escrow_signed) == tx_escrow_signed
|
|
assert b.is_valid_transaction(tx_escrow_signed) == tx_escrow_signed
|
|
|
|
print(json.dumps(tx_escrow_signed, sort_keys=True, indent=4, separators=(',', ':')))
|
|
b.write_transaction(tx_escrow_signed)
|
|
sleep(8)
|
|
|
|
# Retrieve the last transaction of thresholduser1_pub
|
|
tx_escrow_id = {'txid': tx_escrow_signed['id'], 'cid': 0}
|
|
|
|
# Create a base template for output transaction
|
|
tx_escrow_execute = b.create_transaction([testuser2_pub, testuser1_pub], testuser1_pub, tx_escrow_id, 'TRANSFER')
|
|
|
|
# Parse the threshold cryptocondition
|
|
escrow_fulfillment = cc.Fulfillment.from_dict(
|
|
tx_escrow['transaction']['conditions'][0]['condition']['details'])
|
|
|
|
subfulfillment_testuser1 = escrow_fulfillment.get_subcondition_from_vk(testuser1_pub)[0]
|
|
subfulfillment_testuser2 = escrow_fulfillment.get_subcondition_from_vk(testuser2_pub)[0]
|
|
subfulfillment_timeout = escrow_fulfillment.subconditions[0]['body'].subconditions[1]['body']
|
|
subfulfillment_timeout_inverted = escrow_fulfillment.subconditions[1]['body'].subconditions[1]['body']
|
|
|
|
# Get the fulfillment message to sign
|
|
tx_escrow_execute_fulfillment_message = \
|
|
util.get_fulfillment_message(tx_escrow_execute,
|
|
tx_escrow_execute['transaction']['fulfillments'][0],
|
|
serialized=True)
|
|
|
|
escrow_fulfillment.subconditions = []
|
|
|
|
# fulfill execute branch
|
|
fulfillment_execute = cc.ThresholdSha256Fulfillment(threshold=2)
|
|
subfulfillment_testuser1.sign(tx_escrow_execute_fulfillment_message, crypto.SigningKey(testuser1_priv))
|
|
fulfillment_execute.add_subfulfillment(subfulfillment_testuser1)
|
|
fulfillment_execute.add_subfulfillment(subfulfillment_timeout)
|
|
escrow_fulfillment.add_subfulfillment(fulfillment_execute)
|
|
|
|
# do not fulfill abort branch
|
|
condition_abort = cc.ThresholdSha256Fulfillment(threshold=2)
|
|
condition_abort.add_subfulfillment(subfulfillment_testuser2)
|
|
condition_abort.add_subfulfillment(subfulfillment_timeout_inverted)
|
|
escrow_fulfillment.add_subcondition(condition_abort.condition)
|
|
|
|
# create fulfillment and append to transaction
|
|
tx_escrow_execute['transaction']['fulfillments'][0]['fulfillment'] = escrow_fulfillment.serialize_uri()
|
|
|
|
# Time has expired, hence the abort branch can redeem
|
|
tx_escrow_abort = b.create_transaction([testuser2_pub, testuser1_pub], testuser2_pub, tx_escrow_id, 'TRANSFER')
|
|
|
|
# Parse the threshold cryptocondition
|
|
escrow_fulfillment = cc.Fulfillment.from_dict(
|
|
tx_escrow['transaction']['conditions'][0]['condition']['details'])
|
|
|
|
subfulfillment_testuser1 = escrow_fulfillment.get_subcondition_from_vk(testuser1_pub)[0]
|
|
subfulfillment_testuser2 = escrow_fulfillment.get_subcondition_from_vk(testuser2_pub)[0]
|
|
subfulfillment_timeout = escrow_fulfillment.subconditions[0]['body'].subconditions[1]['body']
|
|
subfulfillment_timeout_inverted = escrow_fulfillment.subconditions[1]['body'].subconditions[1]['body']
|
|
|
|
tx_escrow_abort_fulfillment_message = \
|
|
util.get_fulfillment_message(tx_escrow_abort,
|
|
tx_escrow_abort['transaction']['fulfillments'][0],
|
|
serialized=True)
|
|
escrow_fulfillment.subconditions = []
|
|
|
|
# Do not fulfill execute branch
|
|
condition_execute = cc.ThresholdSha256Fulfillment(threshold=2)
|
|
condition_execute.add_subfulfillment(subfulfillment_testuser1)
|
|
condition_execute.add_subfulfillment(subfulfillment_timeout)
|
|
escrow_fulfillment.add_subcondition(condition_execute.condition)
|
|
|
|
# Fulfill abort branch
|
|
fulfillment_abort = cc.ThresholdSha256Fulfillment(threshold=2)
|
|
subfulfillment_testuser2.sign(tx_escrow_abort_fulfillment_message, crypto.SigningKey(testuser2_priv))
|
|
fulfillment_abort.add_subfulfillment(subfulfillment_testuser2)
|
|
fulfillment_abort.add_subfulfillment(subfulfillment_timeout_inverted)
|
|
escrow_fulfillment.add_subfulfillment(fulfillment_abort)
|
|
|
|
tx_escrow_abort['transaction']['fulfillments'][0]['fulfillment'] = escrow_fulfillment.serialize_uri()
|
|
|
|
for i in range(time_sleep - 4):
|
|
valid_execute = b.is_valid_transaction(tx_escrow_execute) == tx_escrow_execute
|
|
valid_abort = b.is_valid_transaction(tx_escrow_abort) == tx_escrow_abort
|
|
|
|
seconds_to_timeout = int(float(time_expire) - float(util.timestamp()))
|
|
print('tx_execute valid: {} - tx_abort valid {} ({}s to timeout)'.format(valid_execute, valid_abort, seconds_to_timeout))
|
|
sleep(1)
|