mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
updated multiple owner docs and cryptoconditions example
This commit is contained in:
parent
079a5296ce
commit
2fdbb5bef8
@ -70,51 +70,51 @@ After a couple of seconds, we can check if the transactions was included in the
|
||||
tx_retrieved = b.get_transaction(tx_signed['id'])
|
||||
|
||||
{
|
||||
"id": "cdb6331f26ecec0ee7e67e4d5dcd63734e7f75bbd1ebe40699fc6d2960ae4cb2",
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
"id":"933cd83a419d2735822a2154c84176a2f419cbd449a74b94e592ab807af23861",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": 32,
|
||||
"public_key": "DTJCqP3sNkZcpoSA8bCtGwZ4ASfRLsMFXZDCmMHzCoeJ",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri": "cc:1:20:uQjL_E_uT1yUsJpVi1X7x2G7B15urzIlKN5fUufehTM:98"
|
||||
"uri":"cc:4:20:oqXTWvR3afHHX8OaOO84kZxS6nH4GEBXD4Vw8Mc5iBo:96"
|
||||
},
|
||||
"new_owners": [
|
||||
"DTJCqP3sNkZcpoSA8bCtGwZ4ASfRLsMFXZDCmMHzCoeJ"
|
||||
"new_owners":[
|
||||
"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"hash": "872fa6e6f46246cd44afdb2ee9cfae0e72885fb0910e2bcf9a5a2a4eadb417b8",
|
||||
"payload": {
|
||||
"msg": "Hello BigchainDB!"
|
||||
"data":{
|
||||
"hash":"872fa6e6f46246cd44afdb2ee9cfae0e72885fb0910e2bcf9a5a2a4eadb417b8",
|
||||
"payload":{
|
||||
"msg":"Hello BigchainDB!"
|
||||
}
|
||||
},
|
||||
"fulfillments": [
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners": [
|
||||
"current_owners":[
|
||||
"3LQ5dTiddXymDhNzETB1rEkp4mA7fEV1Qeiu5ghHiJm9"
|
||||
],
|
||||
"fid": 0,
|
||||
"fulfillment": "cf:1:4:ICKvgXHM8K2jNlKRfkwz3cCvH0OiF5A_-riWsQWXffOMQCyqbFgSDfKTaKRQHypHr5z5jsXzCQ4dKgYkmUo55CMxYs3TT2OxGiV0bZ7Tzn1lcLhpyutGZWm8xIyJKJmmSQQ",
|
||||
"input": null
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:Iq-BcczwraM2UpF-TDPdwK8fQ6IXkD_6uJaxBZd984yxCGX7Csx-S2FBVe8LVyW2sAtmjsOSV0oiw9-s_9qSJB0dDUl_x8YQk5yxNdQyNVWVM1mWSGQL68gMngdmFG8O",
|
||||
"input":null
|
||||
}
|
||||
],
|
||||
"operation": "CREATE",
|
||||
"timestamp": "1460450439.267737"
|
||||
"operation":"CREATE",
|
||||
"timestamp":"1460981667.449279"
|
||||
},
|
||||
"version": 1
|
||||
"version":1
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The new owner of the digital asset is now `DTJCqP3sNkZcpoSA8bCtGwZ4ASfRLsMFXZDCmMHzCoeJ`, which is the public key of `testuser1`.
|
||||
The new owner of the digital asset is now `BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs`, which is the public key of `testuser1`.
|
||||
|
||||
Note that the current owner with public key `3LQ5dTiddXymDhNzETB1rEkp4mA7fEV1Qeiu5ghHiJm9` refers to one of the federation nodes that actually created the asset and assigned it to `testuser1`.
|
||||
|
||||
@ -130,9 +130,11 @@ testuser2_priv, testuser2_pub = crypto.generate_key_pair()
|
||||
|
||||
# retrieve the transaction with condition id
|
||||
tx_retrieved_id = b.get_owned_ids(testuser1_pub).pop()
|
||||
{'cid': 0,
|
||||
'txid': 'cdb6331f26ecec0ee7e67e4d5dcd63734e7f75bbd1ebe40699fc6d2960ae4cb2'}
|
||||
|
||||
{
|
||||
"cid":0,
|
||||
"txid":"933cd83a419d2735822a2154c84176a2f419cbd449a74b94e592ab807af23861"
|
||||
}
|
||||
|
||||
# create a transfer transaction
|
||||
tx_transfer = b.create_transaction(testuser1_pub, testuser2_pub, tx_retrieved_id, 'TRANSFER')
|
||||
@ -147,44 +149,44 @@ b.write_transaction(tx_transfer_signed)
|
||||
tx_transfer_retrieved = b.get_transaction(tx_transfer_signed['id'])
|
||||
|
||||
{
|
||||
"id": "86ce10d653c69acf422a6d017a4ccd27168cdcdac99a49e4a38fb5e0d280c579",
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
"id":"aa11365317cb89bfdae2375bae76d6b8232008f8672507080e3766ca06976dcd",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": 32,
|
||||
"public_key": "7MUjLUFEu12Hk5jb8BZEFgM5JWgSya47SVbqzDqF6ZFQ",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri": "cc:1:20:XmUXkarmpe3n17ITJpi-EFy40qvGZ1C9aWphiiRfjOs:98"
|
||||
"uri":"cc:4:20:DIfyalZvV_9ukoO01mxmK3nxsfAWSKYYF33XDYkbY4E:96"
|
||||
},
|
||||
"new_owners": [
|
||||
"7MUjLUFEu12Hk5jb8BZEFgM5JWgSya47SVbqzDqF6ZFQ"
|
||||
"new_owners":[
|
||||
"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data": null,
|
||||
"fulfillments": [
|
||||
"data":null,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners": [
|
||||
"DTJCqP3sNkZcpoSA8bCtGwZ4ASfRLsMFXZDCmMHzCoeJ"
|
||||
"current_owners":[
|
||||
"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs"
|
||||
],
|
||||
"fid": 0,
|
||||
"fulfillment": "cf:1:4:ILkIy_xP7k9clLCaVYtV-8dhuwdebq8yJSjeX1Ln3oUzQPKxMGutQV0EIRYxg81_Z6gdUHQYHkEyTKxwN7zRFjHNAnIdyU1NxqqohhFQSR-qYho-L-uqPRJcAed-SI7xwAI",
|
||||
"input": {
|
||||
"cid": 0,
|
||||
"txid": "cdb6331f26ecec0ee7e67e4d5dcd63734e7f75bbd1ebe40699fc6d2960ae4cb2"
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:oqXTWvR3afHHX8OaOO84kZxS6nH4GEBXD4Vw8Mc5iBqzkVR6cFJhRvMGKa-Lc81sdYWVu0ZSMPGht-P7s6FZLkRXDqrwwInabLhjx14eABY34oHb6IyWcB-dyQnlVNEI",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"933cd83a419d2735822a2154c84176a2f419cbd449a74b94e592ab807af23861"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation": "TRANSFER",
|
||||
"timestamp": "1460450449.289641"
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1460981677.472037"
|
||||
},
|
||||
"version": 1
|
||||
"version":1
|
||||
}
|
||||
|
||||
```
|
||||
@ -204,7 +206,148 @@ tx_transfer_signed2 = b.sign_transaction(tx_transfer2, testuser1_priv)
|
||||
|
||||
# check if the transaction is valid
|
||||
b.validate_transaction(tx_transfer_signed2)
|
||||
DoubleSpend: input `cdb6331f26ecec0ee7e67e4d5dcd63734e7f75bbd1ebe40699fc6d2960ae4cb2` was already spent
|
||||
DoubleSpend: input `{'cid': 0, 'txid': '933cd83a419d2735822a2154c84176a2f419cbd449a74b94e592ab807af23861'}` was already spent
|
||||
```
|
||||
|
||||
## Multiple Owners
|
||||
|
||||
When creating a transaction to a group of people, one can simply provide an array of `new_owners`:
|
||||
|
||||
```python
|
||||
# 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.write_transaction(tx_multisig_signed)
|
||||
|
||||
# wait a few seconds for the asset to appear on the blockchain
|
||||
|
||||
# retrieve the transaction
|
||||
tx_multisig_retrieved = b.get_transaction(tx_multisig_signed['id'])
|
||||
|
||||
{
|
||||
"id":"a9a6e5c74ea02b8885c83125f1b74a2ba8ca42236ec5e1c358aa1053ec721ccb",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":41,
|
||||
"subfulfillments":[
|
||||
{
|
||||
"bitmask":32,
|
||||
"public_key":"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4,
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"bitmask":32,
|
||||
"public_key":"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4,
|
||||
"weight":1
|
||||
}
|
||||
],
|
||||
"threshold":2,
|
||||
"type":"fulfillment",
|
||||
"type_id":2
|
||||
},
|
||||
"uri":"cc:2:29:DpflJzUSlnTUBx8lD8QUolOA-M9nQnrGwvWSk7f3REc:206"
|
||||
},
|
||||
"new_owners":[
|
||||
"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs",
|
||||
"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":null,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners":[
|
||||
"3LQ5dTiddXymDhNzETB1rEkp4mA7fEV1Qeiu5ghHiJm9"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:Iq-BcczwraM2UpF-TDPdwK8fQ6IXkD_6uJaxBZd984z5qdHRz9Jag68dkOyZS5_YoTR_0WpwiUnBGoNgwjwEuIn5JNm7Kksi0nUnHsWssyXISkmqRnHH-30HQhKjznIH",
|
||||
"input":null
|
||||
}
|
||||
],
|
||||
"operation":"CREATE",
|
||||
"timestamp":"1460981687.501433"
|
||||
},
|
||||
"version":1
|
||||
}
|
||||
```
|
||||
|
||||
The asset can be transfered as soon as each of the `new_owners` sign the transaction.
|
||||
|
||||
To do so, simply provide an array of the necessary private keys to the signing routine:
|
||||
|
||||
```python
|
||||
# create a third testuser
|
||||
testuser3_priv, testuser3_pub = crypto.generate_key_pair()
|
||||
|
||||
# retrieve the multisig transaction
|
||||
tx_multisig_retrieved_id = b.get_owned_ids(testuser2_pub).pop()
|
||||
|
||||
# transfer the asset from the 2 owners to the third testuser
|
||||
tx_multisig_transfer = b.create_transaction([testuser1_pub, testuser2_pub], testuser3_pub, tx_multisig_retrieved_id, 'TRANSFER')
|
||||
|
||||
# sign with both private keys
|
||||
tx_multisig_transfer_signed = b.sign_transaction(tx_multisig_transfer, [testuser1_priv, testuser2_priv])
|
||||
|
||||
# write to bigchain
|
||||
b.write_transaction(tx_multisig_transfer_signed)
|
||||
|
||||
# check if the transaction exists in the bigchain
|
||||
tx_multisig_retrieved = b.get_transaction(tx_multisig_transfer_signed['id'])
|
||||
|
||||
{
|
||||
"assignee":"3LQ5dTiddXymDhNzETB1rEkp4mA7fEV1Qeiu5ghHiJm9",
|
||||
"id":"e689e23f774e7c562eeb310c7c712b34fb6210bea5deb9175e48b68810029150",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"8YN9fALMj9CkeCcmTiM2kxwurpkMzHg9RkwSLJKMasvG",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri":"cc:4:20:cAq6JQJXtwlxURqrksiyqLThB9zh08ZxSPLTDSaReYE:96"
|
||||
},
|
||||
"new_owners":[
|
||||
"8YN9fALMj9CkeCcmTiM2kxwurpkMzHg9RkwSLJKMasvG"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":null,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners":[
|
||||
"BwuhqQX8FPsmqYiRV2CSZYWWsSWgSSQQFHjqxKEuqkPs",
|
||||
"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:oqXTWvR3afHHX8OaOO84kZxS6nH4GEBXD4Vw8Mc5iBrcuiGDNVgpH9SwiuNeYZ-nugSTbxykH8W1eH5UJiunmnBSlKnJb8_QYOQsMAXl3MyLq2pWAyI45ZSG1rr2CksI",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"aa11365317cb89bfdae2375bae76d6b8232008f8672507080e3766ca06976dcd"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1460981697.526878"
|
||||
},
|
||||
"version":1
|
||||
}
|
||||
```
|
||||
|
||||
## Crypto-Conditions
|
||||
@ -238,29 +381,31 @@ The basic workflow for creating a more complex cryptocondition is the following:
|
||||
2. Set up the threshold condition using the [cryptocondition library](https://github.com/bigchaindb/cryptoconditions)
|
||||
3. Update the condition and hash in the transaction template
|
||||
|
||||
We'll illustrate this by an example:
|
||||
We'll illustrate this by a threshold condition where 2 out of 3 `new_owners` need to sign the transaction:
|
||||
|
||||
```python
|
||||
import copy
|
||||
import json
|
||||
|
||||
from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment
|
||||
import cryptoconditions as cc
|
||||
from bigchaindb import util, crypto
|
||||
|
||||
# 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/2-output transaction
|
||||
threshold_tx = b.create_transaction(testuser2_pub, [thresholduser1_pub, thresholduser2_pub], tx_retrieved_id, 'TRANSFER')
|
||||
threshold_tx = b.create_transaction(testuser2_pub, [thresholduser1_pub, thresholduser2_pub, thresholduser3_pub], tx_retrieved_id, 'TRANSFER')
|
||||
|
||||
# create a Threshold Cryptocondition
|
||||
threshold_condition = ThresholdSha256Fulfillment(threshold=2)
|
||||
threshold_condition.add_subfulfillment(Ed25519Fulfillment(public_key=thresholduser1_pub))
|
||||
threshold_condition.add_subfulfillment(Ed25519Fulfillment(public_key=thresholduser2_pub))
|
||||
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'] = {
|
||||
@ -281,64 +426,72 @@ b.write_transaction(threshold_tx_signed)
|
||||
tx_threshold_retrieved = b.get_transaction(threshold_tx_signed['id'])
|
||||
|
||||
{
|
||||
"id": "f0ea4a96afb3b8cafd6336aa3c4b44d1bb0f2b801f61fcb6a44eea4b870ff2e2",
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
"id":"0057d29ff735d91505decf5e7195ea8da675b01676165abf23ea774bbb469383",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": 41,
|
||||
"subfulfillments": [
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":41,
|
||||
"subfulfillments":[
|
||||
{
|
||||
"bitmask": 32,
|
||||
"public_key": "3tuSZ4FitNVWRgK7bGe6pEia7ERmxHmhCxFfFEVbD7g4",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"weight": 1
|
||||
"bitmask":32,
|
||||
"public_key":"8NaGq26YMcEvj8Sc5MnqspKzFTQd1eZBAuuPDw4ERHpz",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4,
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"bitmask": 32,
|
||||
"public_key": "8CvrriTsPZULEXTZW2Hnmg7najZsvXzgTi9NKpJaUdHS",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"weight": 1
|
||||
"bitmask":32,
|
||||
"public_key":"ALE9Agojob28D1fHWCxFXJwpqrYPkcsUs26YksBVj27z",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4,
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"bitmask":32,
|
||||
"public_key":"Cx4jWSGci7fw6z5QyeApCijbwnMpyuhp4C1kzuFc3XrM",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4,
|
||||
"weight":1
|
||||
}
|
||||
],
|
||||
"threshold": 2,
|
||||
"type": "fulfillment",
|
||||
"type_id": 2
|
||||
"threshold":2,
|
||||
"type":"fulfillment",
|
||||
"type_id":2
|
||||
},
|
||||
"uri": "cc:1:29:kiQHpdEiRe24L62KzwQgLu7dxCHaLBfEFLr_xzlswT4:208"
|
||||
"uri":"cc:2:29:FoElId4TE5TU2loonT7sayXhxwcmaJVoCeIduh56Dxw:246"
|
||||
},
|
||||
"new_owners": [
|
||||
"3tuSZ4FitNVWRgK7bGe6pEia7ERmxHmhCxFfFEVbD7g4",
|
||||
"8CvrriTsPZULEXTZW2Hnmg7najZsvXzgTi9NKpJaUdHS"
|
||||
"new_owners":[
|
||||
"8NaGq26YMcEvj8Sc5MnqspKzFTQd1eZBAuuPDw4ERHpz",
|
||||
"ALE9Agojob28D1fHWCxFXJwpqrYPkcsUs26YksBVj27z",
|
||||
"Cx4jWSGci7fw6z5QyeApCijbwnMpyuhp4C1kzuFc3XrM"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data": null,
|
||||
"fulfillments": [
|
||||
"data":null,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners": [
|
||||
"7MUjLUFEu12Hk5jb8BZEFgM5JWgSya47SVbqzDqF6ZFQ"
|
||||
"current_owners":[
|
||||
"qv8DvdNG5nZHWCP5aPSqgqxAvaPJpQj19abRvFCntor"
|
||||
],
|
||||
"fid": 0,
|
||||
"fulfillment": "cf:1:4:IF5lF5Gq5qXt59eyEyaYvhBcuNKrxmdQvWlqYYokX4zrQDSWz8yxBCFaYFKZOLai5ZCoVq28LVoiQ7TL5zkajG-I-BYH2NaKj7CfPBIZHWkMGWfd_UuQWkbhyx07MJ_1Jww",
|
||||
"input": {
|
||||
"cid": 0,
|
||||
"txid": "86ce10d653c69acf422a6d017a4ccd27168cdcdac99a49e4a38fb5e0d280c579"
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:DIfyalZvV_9ukoO01mxmK3nxsfAWSKYYF33XDYkbY4EbD7-_neXJJEe_tVTDc1_EqldlP_ulysFMprcW3VG4gzLzCMMpxA8kCr_pvywSFIEVYJHnI1csMvPivvBGHvkD",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"aa11365317cb89bfdae2375bae76d6b8232008f8672507080e3766ca06976dcd"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation": "TRANSFER",
|
||||
"timestamp": "1460450459.321600"
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1460981707.559401"
|
||||
},
|
||||
"version": 1
|
||||
"version":1
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The transaction can now be transfered by fulfilling the threshold condition.
|
||||
@ -351,29 +504,39 @@ The fulfillment involves:
|
||||
|
||||
|
||||
```python
|
||||
from cryptoconditions.fulfillment import Fulfillment
|
||||
|
||||
thresholduser3_priv, thresholduser3_pub = crypto.generate_key_pair()
|
||||
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, tx_retrieved_id, 'TRANSFER')
|
||||
threshold_tx_transfer = b.create_transaction([thresholduser1_pub, thresholduser2_pub, thresholduser3_pub], thresholduser4_pub, tx_retrieved_id, 'TRANSFER')
|
||||
|
||||
# parse the threshold cryptocondition
|
||||
threshold_fulfillment = Fulfillment.from_json(threshold_tx['transaction']['conditions'][0]['condition']['details'])
|
||||
subfulfillment1 = threshold_fulfillment.subconditions[0]['body']
|
||||
subfulfillment2 = threshold_fulfillment.subconditions[1]['body']
|
||||
threshold_fulfillment = cc.Fulfillment.from_json(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)
|
||||
|
||||
# sign the subconditions
|
||||
# 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)
|
||||
|
||||
# update the fulfillment
|
||||
threshold_tx_transfer['transaction']['fulfillments'][0]['fulfillment'] = threshold_fulfillment.serialize_uri()
|
||||
@ -386,45 +549,48 @@ assert b.validate_transaction(threshold_tx_transfer) == True
|
||||
b.write_transaction(threshold_tx_transfer)
|
||||
|
||||
{
|
||||
"id": "27d1e780526e172fdafb6cfec24b43878b0f8a2c34e962546ba4932ef7662646",
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
"assignee":"3LQ5dTiddXymDhNzETB1rEkp4mA7fEV1Qeiu5ghHiJm9",
|
||||
"id":"a45b2340c59df7422a5788b3c462dee708a18cdf09d1a10bd26be3f31af4b8d7",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": 32,
|
||||
"public_key": "4SwVNiYRykGw1ixgKH75k97ipCnmm5QpwNwzQdCKLCzH",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"ED2pyPfsbNRTHkdMnaFkAwCSpZWRmbaM1h8fYzgRRMmc",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri": "cc:1:20:MzgxMS8Zt2XZrSA_dFk1d64nwUz16knOeKkxc5LyIv4:98"
|
||||
"uri":"cc:4:20:xDz3NhRG-3eVzIB9sgnd99LKjOyDF-KlxWuf1TgNT0s:96"
|
||||
},
|
||||
"new_owners": [
|
||||
"4SwVNiYRykGw1ixgKH75k97ipCnmm5QpwNwzQdCKLCzH"
|
||||
"new_owners":[
|
||||
"ED2pyPfsbNRTHkdMnaFkAwCSpZWRmbaM1h8fYzgRRMmc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data": null,
|
||||
"fulfillments": [
|
||||
"data":null,
|
||||
"fulfillments":[
|
||||
{
|
||||
"current_owners": [
|
||||
"3tuSZ4FitNVWRgK7bGe6pEia7ERmxHmhCxFfFEVbD7g4",
|
||||
"8CvrriTsPZULEXTZW2Hnmg7najZsvXzgTi9NKpJaUdHS"
|
||||
"current_owners":[
|
||||
"8NaGq26YMcEvj8Sc5MnqspKzFTQd1eZBAuuPDw4ERHpz",
|
||||
"ALE9Agojob28D1fHWCxFXJwpqrYPkcsUs26YksBVj27z",
|
||||
"Cx4jWSGci7fw6z5QyeApCijbwnMpyuhp4C1kzuFc3XrM"
|
||||
],
|
||||
"fid": 0,
|
||||
"fulfillment": "cf:1:2:AgIBYwQgKwNKM5oJUhL3lUJ3Xj0dzePTH_1BOxcIry5trRxnNXFANabre0P23pzs3liGozZ-cua3zLZuZIc4UA-2Eb_3oi0zFZKHlL6_PrfxpZFp4Mafsl3Iz1yGVz8s-x5jcbahDwABYwQgaxAYvRMOihIk-M4AZYFB2mlf4XjEqhiOaWpqinOYiXFAuQm7AMeXDs4NCeFI4P6YeL3RqNZqyTr9OsNHZ9JgJLZ2ER1nFpwsLhOt4TJZ01Plon7r7xA2GFKFkw511bRWAQA",
|
||||
"input": {
|
||||
"cid": 0,
|
||||
"txid": "f0ea4a96afb3b8cafd6336aa3c4b44d1bb0f2b801f61fcb6a44eea4b870ff2e2"
|
||||
"fid":0,
|
||||
"fulfillment":"cf:2:AQIBAwEBACcABAEgILGLuLLaNHo-KE59tkrpYmlVeucu16Eg9TcSuBqnMVwmAWABAWMABGBtiKCT8NBtSdnxJNdGYkyWqoRy2qOeNZ5UdUvpALcBD4vGRaohuVP9pQYNHpAA5GjTNNQT9CVMB67D8QL_DJsRU8ICSIVIG2P8pRqX6oia-304Xqq67wY-wLh_3IKlUg0AAQFjAARgiqYTeWkT6-jRMriCK4i8ceE2TwPys0JXgIrbw4kbwElVNnc7Aqw5c-Ts8-ymLp3d9_xTIb3-mPaV4JjhBqcobKuq2msJAjrxZOEeuYuAyC0tpduwTajOyp_Kmwzhdm8PAA",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"0057d29ff735d91505decf5e7195ea8da675b01676165abf23ea774bbb469383"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation": "TRANSFER",
|
||||
"timestamp": "1460450469.337543"
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1460981717.579700"
|
||||
},
|
||||
"version": 1
|
||||
"version":1
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
2
setup.py
2
setup.py
@ -71,7 +71,7 @@ setup(
|
||||
'rethinkdb==2.2.0.post4',
|
||||
'pysha3==0.3',
|
||||
'pytz==2015.7',
|
||||
'cryptoconditions==0.2.0',
|
||||
'cryptoconditions==0.2.1',
|
||||
'statsd==3.2.1',
|
||||
'python-rapidjson==0.0.6',
|
||||
'logstats==0.2.1',
|
||||
|
@ -1310,7 +1310,7 @@ class TestCryptoconditions(object):
|
||||
first_tx_fulfillment.sign(first_tx_fulfillment_message, crypto.SigningKey(user_sk))
|
||||
first_tx['transaction']['fulfillments'][0]['fulfillment'] = first_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(first_tx)
|
||||
assert b.validate_transaction(first_tx) == first_tx
|
||||
assert b.is_valid_transaction(first_tx) == first_tx
|
||||
|
||||
b.write_transaction(first_tx)
|
||||
@ -1329,20 +1329,22 @@ class TestCryptoconditions(object):
|
||||
next_tx_fulfillment.sign(next_tx_fulfillment_message, crypto.SigningKey(other_sk))
|
||||
next_tx['transaction']['fulfillments'][0]['fulfillment'] = next_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(next_tx)
|
||||
assert b.validate_transaction(next_tx) == next_tx
|
||||
assert b.is_valid_transaction(next_tx) == next_tx
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_override_condition_and_fulfillment_transfer_threshold(self, b, user_vk, user_sk):
|
||||
other1_sk, other1_vk = crypto.generate_key_pair()
|
||||
other2_sk, other2_vk = crypto.generate_key_pair()
|
||||
other3_sk, other3_vk = crypto.generate_key_pair()
|
||||
|
||||
first_input_tx = b.get_owned_ids(user_vk).pop()
|
||||
first_tx = b.create_transaction(user_vk, [other1_vk, other2_vk], first_input_tx, 'TRANSFER')
|
||||
first_tx = b.create_transaction(user_vk, [other1_vk, other2_vk, other3_vk], first_input_tx, 'TRANSFER')
|
||||
|
||||
first_tx_condition = cc.ThresholdSha256Fulfillment(threshold=2)
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other1_vk))
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other2_vk))
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other3_vk))
|
||||
|
||||
first_tx['transaction']['conditions'][0]['condition'] = {
|
||||
'details': json.loads(first_tx_condition.serialize_json()),
|
||||
@ -1353,7 +1355,7 @@ class TestCryptoconditions(object):
|
||||
|
||||
first_tx_signed = b.sign_transaction(first_tx, user_sk)
|
||||
|
||||
assert b.validate_transaction(first_tx_signed)
|
||||
assert b.validate_transaction(first_tx_signed) == first_tx_signed
|
||||
assert b.is_valid_transaction(first_tx_signed) == first_tx_signed
|
||||
|
||||
b.write_transaction(first_tx_signed)
|
||||
@ -1364,7 +1366,7 @@ class TestCryptoconditions(object):
|
||||
|
||||
next_input_tx = b.get_owned_ids(other1_vk).pop()
|
||||
# create another transaction with the same input
|
||||
next_tx = b.create_transaction([other1_vk, other2_vk], user_vk, next_input_tx, 'TRANSFER')
|
||||
next_tx = b.create_transaction([other1_vk, other2_vk, other3_vk], user_vk, next_input_tx, 'TRANSFER')
|
||||
|
||||
next_tx_fulfillment = next_tx['transaction']['fulfillments'][0]
|
||||
next_tx_fulfillment_message = util.get_fulfillment_message(next_tx, next_tx_fulfillment, serialized=True)
|
||||
@ -1375,9 +1377,70 @@ class TestCryptoconditions(object):
|
||||
next_tx_subfulfillment2 = cc.Ed25519Fulfillment(public_key=other2_vk)
|
||||
next_tx_subfulfillment2.sign(next_tx_fulfillment_message, crypto.SigningKey(other2_sk))
|
||||
next_tx_fulfillment.add_subfulfillment(next_tx_subfulfillment2)
|
||||
# need to add remaining (unsigned) fulfillment as a condition
|
||||
next_tx_subfulfillment3 = cc.Ed25519Fulfillment(public_key=other3_vk)
|
||||
next_tx_fulfillment.add_subcondition(next_tx_subfulfillment3.condition)
|
||||
next_tx['transaction']['fulfillments'][0]['fulfillment'] = next_tx_fulfillment.serialize_uri()
|
||||
|
||||
assert b.validate_transaction(next_tx)
|
||||
assert b.validate_transaction(next_tx) == next_tx
|
||||
assert b.is_valid_transaction(next_tx) == next_tx
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_override_condition_and_fulfillment_transfer_threshold_from_json(self, b, user_vk, user_sk):
|
||||
other1_sk, other1_vk = crypto.generate_key_pair()
|
||||
other2_sk, other2_vk = crypto.generate_key_pair()
|
||||
other3_sk, other3_vk = crypto.generate_key_pair()
|
||||
|
||||
first_input_tx = b.get_owned_ids(user_vk).pop()
|
||||
first_tx = b.create_transaction(user_vk, [other1_vk, other2_vk, other3_vk], first_input_tx, 'TRANSFER')
|
||||
|
||||
first_tx_condition = cc.ThresholdSha256Fulfillment(threshold=2)
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other1_vk))
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other2_vk))
|
||||
first_tx_condition.add_subfulfillment(cc.Ed25519Fulfillment(public_key=other3_vk))
|
||||
|
||||
first_tx['transaction']['conditions'][0]['condition'] = {
|
||||
'details': json.loads(first_tx_condition.serialize_json()),
|
||||
'uri': first_tx_condition.condition.serialize_uri()
|
||||
}
|
||||
# conditions have been updated, so hash needs updating
|
||||
first_tx['id'] = util.get_hash_data(first_tx)
|
||||
|
||||
first_tx_signed = b.sign_transaction(first_tx, user_sk)
|
||||
|
||||
assert b.validate_transaction(first_tx_signed) == first_tx_signed
|
||||
assert b.is_valid_transaction(first_tx_signed) == first_tx_signed
|
||||
|
||||
b.write_transaction(first_tx_signed)
|
||||
|
||||
# create and write block to bigchain
|
||||
block = b.create_block([first_tx])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
next_input_tx = b.get_owned_ids(other1_vk).pop()
|
||||
# create another transaction with the same input
|
||||
next_tx = b.create_transaction([other1_vk, other2_vk, other3_vk], user_vk, next_input_tx, 'TRANSFER')
|
||||
|
||||
next_tx_fulfillment = next_tx['transaction']['fulfillments'][0]
|
||||
next_tx_fulfillment_message = util.get_fulfillment_message(next_tx, next_tx_fulfillment, serialized=True)
|
||||
|
||||
# parse the threshold cryptocondition
|
||||
next_tx_fulfillment = cc.Fulfillment.from_json(first_tx['transaction']['conditions'][0]['condition']['details'])
|
||||
|
||||
subfulfillment1 = next_tx_fulfillment.get_subcondition_from_vk(other1_vk)[0]
|
||||
subfulfillment2 = next_tx_fulfillment.get_subcondition_from_vk(other2_vk)[0]
|
||||
subfulfillment3 = next_tx_fulfillment.get_subcondition_from_vk(other3_vk)[0]
|
||||
|
||||
next_tx_fulfillment.subconditions = []
|
||||
# sign the subconditions until threshold of 2 is reached
|
||||
subfulfillment1.sign(next_tx_fulfillment_message, crypto.SigningKey(other1_sk))
|
||||
next_tx_fulfillment.add_subfulfillment(subfulfillment1)
|
||||
subfulfillment2.sign(next_tx_fulfillment_message, crypto.SigningKey(other2_sk))
|
||||
next_tx_fulfillment.add_subfulfillment(subfulfillment2)
|
||||
next_tx_fulfillment.add_subcondition(subfulfillment3.condition)
|
||||
|
||||
next_tx['transaction']['fulfillments'][0]['fulfillment'] = next_tx_fulfillment.serialize_uri()
|
||||
assert b.validate_transaction(next_tx) == next_tx
|
||||
assert b.is_valid_transaction(next_tx) == next_tx
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
@ -1401,7 +1464,7 @@ class TestCryptoconditions(object):
|
||||
|
||||
first_tx_signed = b.sign_transaction(first_tx, user_sk)
|
||||
|
||||
assert b.validate_transaction(first_tx_signed)
|
||||
assert b.validate_transaction(first_tx_signed) == first_tx_signed
|
||||
assert b.is_valid_transaction(first_tx_signed) == first_tx_signed
|
||||
|
||||
b.write_transaction(first_tx_signed)
|
||||
|
@ -31,11 +31,18 @@ sleep(10)
|
||||
|
||||
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'])
|
||||
# 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')
|
||||
@ -50,6 +57,8 @@ sleep(10)
|
||||
|
||||
# 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=(',', ':')))
|
||||
|
||||
|
||||
# create another transfer transaction with the same input
|
||||
tx_transfer2 = b.create_transaction(testuser1_pub, testuser2_pub, tx_retrieved_id, 'TRANSFER')
|
||||
@ -63,20 +72,54 @@ try:
|
||||
except exceptions.DoubleSpend as e:
|
||||
print(e)
|
||||
|
||||
# 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.write_transaction(tx_multisig_signed)
|
||||
|
||||
# wait a few seconds for the asset to appear on the blockchain
|
||||
sleep(10)
|
||||
|
||||
# retrieve the transaction
|
||||
tx_multisig_retrieved = b.get_transaction(tx_multisig_signed['id'])
|
||||
|
||||
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])
|
||||
|
||||
b.write_transaction(tx_multisig_transfer_signed)
|
||||
|
||||
# wait a few seconds for the asset to appear on the blockchain
|
||||
sleep(10)
|
||||
|
||||
# retrieve the transaction
|
||||
tx_multisig_retrieved = b.get_transaction(tx_multisig_transfer_signed['id'])
|
||||
|
||||
print(json.dumps(tx_multisig_transfer_signed, sort_keys=True, indent=4, separators=(',', ':')))
|
||||
|
||||
# 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/2-output transaction
|
||||
threshold_tx = b.create_transaction(testuser2_pub, [thresholduser1_pub, thresholduser2_pub], tx_retrieved_id, 'TRANSFER')
|
||||
# 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 Threshold Cryptocondition
|
||||
# create a 2-out-of-3 Threshold Cryptocondition
|
||||
threshold_condition = ThresholdSha256Fulfillment(threshold=2)
|
||||
threshold_condition.add_subfulfillment(Ed25519Fulfillment(public_key=thresholduser1_pub))
|
||||
threshold_condition.add_subfulfillment(Ed25519Fulfillment(public_key=thresholduser2_pub))
|
||||
threshold_condition.add_subfulfillment(Ed25519Fulfillment(public_key=thresholduser3_pub))
|
||||
|
||||
# update the condition in the newly created transaction
|
||||
threshold_tx['transaction']['conditions'][0]['condition'] = {
|
||||
@ -97,28 +140,41 @@ sleep(10)
|
||||
|
||||
# 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=(',', ':')))
|
||||
|
||||
thresholduser3_priv, thresholduser3_pub = crypto.generate_key_pair()
|
||||
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, tx_retrieved_id, 'TRANSFER')
|
||||
threshold_tx_transfer = b.create_transaction([thresholduser1_pub, thresholduser2_pub, thresholduser3_pub],
|
||||
thresholduser4_pub, tx_retrieved_id, 'TRANSFER')
|
||||
|
||||
# parse the threshold cryptocondition
|
||||
threshold_fulfillment = Fulfillment.from_json(threshold_tx['transaction']['conditions'][0]['condition']['details'])
|
||||
subfulfillment1 = threshold_fulfillment.subconditions[0]['body']
|
||||
subfulfillment2 = threshold_fulfillment.subconditions[1]['body']
|
||||
|
||||
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)
|
||||
|
||||
# sign the subconditions
|
||||
# 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
|
||||
|
||||
@ -126,7 +182,10 @@ threshold_tx_transfer['transaction']['fulfillments'][0]['fulfillment'] = thresho
|
||||
|
||||
assert b.verify_signature(threshold_tx_transfer) == True
|
||||
|
||||
assert b.validate_transaction(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=(',', ':')))
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user