Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a transaction/fulfillment/condition validation utility #110

Open
sbellem opened this issue Oct 14, 2016 · 3 comments
Open

Provide a transaction/fulfillment/condition validation utility #110

sbellem opened this issue Oct 14, 2016 · 3 comments

Comments

@sbellem
Copy link
Contributor

sbellem commented Oct 14, 2016

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

@sbellem sbellem self-assigned this Oct 14, 2016
@sbellem sbellem changed the title Provide a transaction validation utility Provide a transaction/fulfilment/condition validation utility Oct 27, 2016
@sbellem sbellem changed the title Provide a transaction/fulfilment/condition validation utility Provide a transaction/fulfillment/condition validation utility Oct 27, 2016
@arunkumarsekar
Copy link

arunkumarsekar commented Mar 16, 2017

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"}

@sbellem
Copy link
Contributor Author

sbellem commented Apr 5, 2017

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.

@StatelessToken
Copy link

What happened with this? The Docs lead here in a Todo box.

Is the above solution functional at present?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants