bigchaindb-driver
bigchaindb-driver copied to clipboard
Provide a transaction/fulfillment/condition validation utility
To support cases similar to:
>>> # 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
>>> b.validate_transaction(tx_transfer_signed2)
DoubleSpend: input `{'cid': 0, 'txid': '933cd83a419d2735822a2154c84176a2f419cbd449a74b94e592ab807af23861'}` was already spent
see https://github.com/bigchaindb/bigchaindb/blob/master/docs/source/drivers-clients/python-server-api-examples.md#double-spends
Here we go... Hand crafted Hash-Locked ...
import hashlib import json import time
from bigchaindb_driver import BigchainDB import cryptoconditions as cc from cryptoconditions.crypto import Ed25519SigningKey as SigningKey
Create Transaction
class CreateTxnManager():
def __init__(self, params):
self.bigchaindb_url = 'http://172.16.217.94:9984'
self.b = self.getChainDriver()
self.condition = ''
self.owner_pub_key = params.get('owner_public_key')
self.owner_priv_key = params.get('owner_private_key')
self.requester_pub_key = params.get('requester_publickey')
def getChainDriver(self):
return BigchainDB(self.bigchaindb_url)
def txInput(self):
input_ = {
'fulfillment': None,
'fulfills': None,
'owners_before': (self.owner_pub_key,)
}
return input_
def txOutput(self):
secret = str.encode(self.secret_message)
tx_condition = cc.PreimageSha256Fulfillment(preimage=secret)
self.condition = tx_condition
output = {
'amount': 1,
'condition': {
'details': tx_condition.to_dict(),
'uri': tx_condition.condition_uri,
},
'public_keys': (self.owner_pub_key,),
}
return output
def tx_prepare(self, assets):
return {
'operation': 'CREATE',
'asset': {
'data': assets
},
'metadata': None,
'outputs': (self.txOutput(),),
'inputs': (self.txInput(),),
'version': '0.9',
}
def createAsset(self, params, assets):
key = str(time.time())
self.secret_message = hashlib.sha3_256(key.encode()).hexdigest()
return self.deployAsset(assets)
def deployAsset(self, assets):
tx = self.tx_prepare(assets)
json_str_tx = json.dumps(
tx,
sort_keys=True,
separators=(',', ':'),
ensure_ascii=False,
)
creation_txid = hashlib.sha3_256(json_str_tx.encode()).hexdigest()
tx['id'] = creation_txid
fl_str_tx = json.dumps(
tx,
sort_keys=True,
separators=(',', ':'),
ensure_ascii=False,
)
tx['inputs'][0]['fulfillment'] = self.condition.serialize_uri()
returned_creation_tx = self.b.transactions.send(tx)
if self.validateTx(tx['id']) == 'valid':
return {'status':'True', "token": self.secret_message, "create_txn_id": tx['id'] }
else:
return {'status':'False'}
def validateTx(self, txid):
trails = 0
while trails < 100:
try:
if self.b.transactions.status(txid).get('status') == 'valid':
break
except bigchaindb_driver.exceptions.NotFoundError:
trails += 1
return self.b.transactions.status(txid).get('status')
Transfer txn
class TranferTxManager():
# token : secret_token
def __init__(self, token):
self.bigchaindb_url = 'http://172.16.217.94:9984'
self.b = self.getChainDriver()
self.preimage = token
def getChainDriver(self):
return BigchainDB(self.bigchaindb_url)
def validateTx(self, txid):
trails = 0
while trails < 100:
try:
if self.b.transactions.status(txid).get('status') == 'valid':
break
except bigchaindb_driver.exceptions.NotFoundError:
trails += 1
return self.b.transactions.status(txid).get('status')
"""
data = {
'txnId': <Create TXN ID>,
'pubkey': "<requester pub key>"
}
"""
def trasferAsset(self, data):
data = self.getTxnDetails()
if data and data.get('txId'):
if self.validateTx(data.get('txId')) == 'valid':
return self.prepareAssetTransfer(data)
else:
return {"status":"False", "error": "invalid create transaction"}
return {"status":"False", "error": "invalid attempt"}
def transferInput(self, tx):
index = 0
output = tx['outputs'][index]
input_ = {
'fulfillment': output['condition']['details'],
'fulfills': {
'output': index,
'txid': tx['id'],
},
'owners_before': output['public_keys'],
}
return input_
def prepareAssetTransfer(self, data):
txnid = data.get('txId')
tx = self.b.transactions.retrieve(txnid)
transferAsset = {
'id': tx['id']
}
transferTx = self.b.transactions.prepare(
operation='TRANSFER',
recipients=data.get('pubkey'),
asset=transferAsset,
inputs=self.transferInput(tx),
)
transfer_tx_condition = cc.PreimageSha256Fulfillment(preimage=str.encode(self.preimage))
if tx['inputs'][0]['fulfillment'] == transfer_tx_condition.serialize_uri():
transferTx['inputs'][0]['fulfillment'] = transfer_tx_condition.serialize_uri()
sent_transfer_tx = self.b.transactions.send(transferTx)
return {"status":"True", "asset":tx['asset']['data']}
else:
return {"status":"False", "error": "invalid transaction id"}
Hi @arunkumarsekar! Sorry for not getting back to you earlier. Thanks for sharing your solution! We will look into how we can integrate it soon.
What happened with this? The Docs lead here in a Todo box.
Is the above solution functional at present?