Closed batlogs closed 7 years ago
@batlogs I think I see the problem. When preparing the TRANSFER transaction to transfer the asset to Rob:
tx_transfer = bdb.transactions.prepare(operation='TRANSFER',inputs=input_,asset=transfer_asset,recipients=rob.public_key,)
Notice how inputs=input_
and input_
is the same input_
as was used when transferring to Bob, but it should be different because that input is supposed to fulfill a different output.
(CREATE tx) --> (TRANSFER tx 1) --> (TRANSFER tx 2)
When preparing (TRANSFER tx 1) you were fulfilling an output on (CREATE tx), but when preparing (TRANSFER tx 2), you are fulfilling an output on (TRANSFER tx 1).
So does it mean I have to create a new asset to accomplish Transfer tx2 ? (CREATE tx1) --> (TRANSFER tx 1) --> Transfer to Bob (CREATE tx2) --> (TRANSFER tx 2) --> Transfer to Rob
No. It's the same asset changing hands. The input for (TRANSFER tx 2) should be the output of (TRANSFER tx 1).
#Alice Key Pair
alice = generate_keypair()
digital_asset_payload = {'data': {'msg': 'Hello BigchainDB!'}}
tx = bdb.transactions.prepare(operation='CREATE',signers=alice.public_key,asset=digital_asset_payload)
signed_tx = bdb.transactions.fulfill(tx, private_keys=alice.private_key)
sent_tx = bdb.transactions.send(signed_tx)
tx_retrieved = bdb.transactions.retrieve(tx['id'])
output_index = 0
output = tx['outputs'][output_index]
#Transfer to Bob
input_ = {'fulfillment': output['condition']['details'],'fulfills': {'output_index': output_index,'transaction_id': tx['id'],},'owners_before': output['public_keys'],}
transfer_asset_id = tx['id']
transfer_asset = {'id': transfer_asset_id,}
bob = generate_keypair()
tx_transfer = bdb.transactions.prepare(operation='TRANSFER',inputs=input_,asset=transfer_asset,recipients=bob.public_key,)
signed_tx_transfer = bdb.transactions.fulfill(tx_transfer,private_keys=alice.private_key,)
sent_tx_transfer = bdb.transactions.send(signed_tx_transfer)
#Transfer to Rob
tx_retrieved = bdb.transactions.retrieve(tx['id'])
output = tx['outputs'][output_index]
input_ = {'fulfillment': output['condition']['details'],'fulfills': {'output_index': output_index,'transaction_id': tx['id'],},'owners_before': output['public_keys'],}
transfer_asset_id = tx['id']
transfer_asset = {'id': transfer_asset_id,}
rob = generate_keypair()
tx_transfer = bdb.transactions.prepare(operation='TRANSFER',inputs=input_,asset=transfer_asset,recipients=rob.public_key,)
signed_tx_transfer = bdb.transactions.fulfill(tx_transfer,private_keys=bob.private_key,)
sent_tx_transfer = bdb.transactions.send(signed_tx_transfer)
sent_tx_transfer == signed_tx_transfer
gives Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/bigchaindb_driver/offchain.py", line 351, in fulfill_transaction signed_transaction = transaction_obj.sign(private_keys) File "/usr/local/lib/python3.6/site-packages/bigchaindb/common/transaction.py", line 758, in sign self.inputs[i] = self._signinput(input, tx_serialized, key_pairs) File "/usr/local/lib/python3.6/site-packages/bigchaindb/common/transaction.py", line 779, in _sign_input key_pairs) File "/usr/local/lib/python3.6/site-packages/bigchaindb/common/transaction.py", line 813, in _sign_simple_signature_fulfillment .format(public_key)) bigchaindb.common.exceptions.KeypairMismatchException: Public key FoDnJ3tQWV9N1D48pmZMKwp8BEewfgyiRxAdKx39g4UP is not a pair to any of the private keys
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "
can you please give an example for "The input for (TRANSFER tx 2) should be the output of (TRANSFER tx 1)" and help
I think you need to add one line after the comment #Transfer to Rob
:
#Transfer to Rob
tx = sent_tx_transfer
because in the code you shared above, tx
was still the original (unsigned) CREATE tx.
I did try that, but now I get the below error
tx = sent_tx_transfer tx_retrieved = bdb.transactions.retrieve(tx['id']) output_index = 0 output = tx['outputs'][outputindex] input = {'fulfillment': output['condition']['details'],'fulfills': {'output_index': output_index,'transaction_id': tx['id'],},'owners_before': output['public_keys'],} transfer_asset_id = tx['id'] transfer_asset = {'id': transfer_asset_id,} rob = generate_keypair() txtransfer = bdb.transactions.prepare(operation='TRANSFER',inputs=input,asset=transfer_asset,recipients=rob.public_key,) signed_tx_transfer = bdb.transactions.fulfill(tx_transfer,private_keys=bob.private_key,) sent_tx_transfer = bdb.transactions.send(signed_tx_transfer) Traceback (most recent call last): File "
", line 1, in File "/usr/local/lib/python3.6/site-packages/bigchaindb_driver/driver.py", line 319, in send method='POST', path=self.path, json=transaction, headers=headers) File "/usr/local/lib/python3.6/site-packages/bigchaindb_driver/transport.py", line 58, in forward_request headers=headers, File "/usr/local/lib/python3.6/site-packages/bigchaindb_driver/connection.py", line 57, in request raise exc_cls(response.status_code, text, json) bigchaindb_driver.exceptions.BadRequest: (400, '{\n "message": "Invalid transaction (AssetIdMismatch): The asset id of the input does not match the asset id of the transaction", \n "status": 400\n}\n', {'message': 'Invalid transaction (AssetIdMismatch): The asset id of the input does not match the asset id of the transaction', 'status': 400})
Oh, right, the id of an asset is always the id of the CREATE transaction where that asset was originally created. In this case, that should be the id of (CREATE tx 1). Your code is setting transfer_asset_id = tx['id']
but now tx
is the unsigned (TRANSFER tx 1), not (CREATE tx 1). One way to fix that would be to delete two lines in the #Transfer to Rob
section:
transfer_asset_id = tx['id']
transfer_asset = {'id': transfer_asset_id,}
That way, those two variables will stay the same, as they should, because the asset id doesn't change.
Brilliant! it works. Thanks for all your help
alice = generate_keypair() bob= generate_keypair() matt = generate_keypair()
#Generates public and private key for Alice and Bob
''' Here the asset being transferred is a bicycle which belongs to Alice The variable below contains a data property which contains the information about the bicycle '''
bicycle= { 'data':{ 'bicycle':{ 'serial_number' : 'XX2334C', 'manufacturer':'bkfab', },
},
} metadata={'Country':'France'} #Any dictionary can be used as Metadata prepared_creation_tx= bdb.transactions.prepare(operation='CREATE',signers=alice.public_key,asset=bicycle,metadata=metadata) #This creates a digital asset fulfilled_creation_tx=bdb.transactions.fulfill(prepared_creation_tx,private_keys=alice.private_key) #the transaction gets authenticated using Alice's private key sent_creation_tx=bdb.transactions.send(fulfilled_creation_tx) #the authorized transaction is now sent over to the BigchainDB print(sent_creation_tx==fulfilled_creation_tx) txid= fulfilled_creation_tx['id'] #contains the transaction id print('transactions id is ') print(txid) ''' The code below keeps checking the transaction until it become valid As it takes a some time before the transaction is deemed as valid by the BigchainDB Cluster
'''
trials = 0
while trials < 100: try: if bdb.transactions.status(txid).get('status') == 'valid': break except bigchaindb_driver.exceptions.NotFoundError: trials += 1 print(bdb.transactions.status(txid))
creation_tx= fulfilled_creation_tx #Alice retrieves the transaction print("Alice retrieves") print(creation_tx)
''' Preparing a transaction To get inforamtion about the id of the asset we are transferrring ''' asset_id= creation_tx['id'] transfer_asset={ 'id' :asset_id, }
''' Transfer transaction ''' output_index=0 output= creation_tx['outputs'][output_index] transfer_input={ 'fulfillment': output['condition']['details'], 'fulfills':{ 'output_index':output_index, 'transaction_id':creation_tx['id'], }, 'owners_before': output['public_keys'], }
print("public_keys 1") print(output['public_keys']) prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=bob.public_key, )
fulfilled_transfer_tx= bdb.transactions.fulfill( prepared_transfer_tx, private_keys= alice.private_key, )
sent_transfer_tx=bdb.transactions.send(fulfilled_transfer_tx) print(sent_transfer_tx==fulfilled_transfer_tx) print("Fulfilled transfer looks like") print(fulfilled_transfer_tx)
print("Is the bob the owner?",sent_transfer_tx['outputs'][0]['public_keys'][0]==bob.public_key) print("Was Alice the previous owner? ",fulfilled_transfer_tx['inputs'][0]['owners_before'][0]==alice.public_key)
transfer_tx=fulfilled_transfer_tx asset_id = transfer_tx['id'] transfer_asset={ 'id' :asset_id, } print ("Helllooo") print (transfer_tx['asset']['id'])
output= transfer_tx['outputs'][output_index] transfer_input={ 'fulfillment': output['condition']['details'], 'fulfills':{ 'output_index':output_index, 'transaction_id':transfer_tx['asset']['id'], }, 'owners_before': output['public_keys'], }
print("public_keys 1") print(output['public_keys']) prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=matt.public_key, )
fulfilled_transfer_tx= bdb.transactions.fulfill( prepared_transfer_tx, private_keys= bob.private_key, )
sent_transfer_tx=bdb.transactions.send(fulfilled_transfer_tx). I get the error on this line print(sent_transfer_tx==fulfilled_transfer_tx) print("Fulfilled transfer looks like") print(fulfilled_transfer_tx)
Error message : bigchaindb_driver.exceptions.BadRequest: (400, '{\n "message": "Invalid transaction (InvalidSignature): Transaction signature is invalid.", \n "status": 400\n}\n', {'message': 'Invalid transaction (InvalidSignature): Transaction signature is invalid.', 'status': 400})
print("Is matt the owner?",sent_transfer_tx['outputs'][0]['public_keys'][0]==bob.public_key) print("Was Alice the previous owner? ",fulfilled_transfer_tx['inputs'][0]['owners_before'][0]==alice.public_key) print("Was Bob the previous owner? ",fulfilled_transfer_tx['inputs'][0]['owners_before'][1]==alice.public_key)
Description
I create Alice Alice creates an asset Alice transfers the Asset to Bob Bob wants to transfer the Asset to Rob --> Missing Key Exception (I use Bob's Private Key)
What I Did