-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBigchaindbConnector.py
153 lines (124 loc) · 5.48 KB
/
BigchaindbConnector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from IBlockchainConnector import BlockchainConnector
from bigchaindb_driver import BigchainDB
from bigchaindb_driver.crypto import generate_keypair
class BigchaindbConnector(BlockchainConnector):
# Bigchaindb requires list of endpoints given as full urls and
# optional dictionary of parameters called headers (e.g., app_id)
def __init__(self, endpoints = ['http://localhost:9984'], params = None):
BlockchainConnector.__init__(self, 'Bigchaindb', endpoints)
self.headers = params
self.conn = BigchainDB(*self.endpoints, headers = self.headers)
self.conn.info() #if this fails exception generated
def getConnectorConfig(self):
config = dict()
config['backend'] = self.backend
config['endpoints'] = self.endpoints
config['params'] = self.headers
return config
def createParticipant(self, participant=None, participant_type=None):
#for bigchain a participant is just a set of private/public keys
k = generate_keypair()
keys = dict()
keys['private_key'] = k.private_key
keys['public_key'] = k.public_key
return keys
def updateParticipant(self, participant=None, participant_type=None):
return self.createParticipant()
def submitAssetCreateTransaction(self, casset, asset_type, ass_data, owner):
asset = dict()
# In asset there must be a 'data' property with the data in it.
asset['data'] = casset
# prepare asset creation for blockchain transaction
prepared_create_tx = self.conn.transactions.prepare(
operation = 'CREATE',
signers = owner['public_key'],
asset = asset,
metadata = ass_data
)
# The transaction now needs to be fulfilled by signing it with the private key:
fulfilled_create_tx = self.conn.transactions.fulfill(
prepared_create_tx,
private_keys=owner['private_key']
)
print('BigChainConnector>> Asset prepared, signed and verified for submission')
# Send transaction over to a BigchainDB node
# Commit (opposed to async) waits until the transaction is committed to a block or a timeout is reached.
self.conn.transactions.send_commit(fulfilled_create_tx)
txid = fulfilled_create_tx['id']
print('BigChainConnector>> Asset committed to blockchain ledger with transaction id: ' + txid)
resp = {
'asset_id': txid, #CREATE ops have same asset and trans id
'trans_id': txid,
'status_code': 200
}
return resp
def submitAssetAppendTransaction(self, asset_id, asset_type, ass_data, prev_trans_id, prev_owner, new_owner):
prev_trans = self.conn.transactions.retrieve(prev_trans_id)
if not prev_trans:
return
transfer_asset = {
'id': asset_id
}
output_index = 0
output = prev_trans['outputs'][output_index]
transfer_input = {
'fulfillment': output['condition']['details'],
'fulfills': {
'output_index': output_index,
'transaction_id': prev_trans['id'],
},
'owners_before': output['public_keys'],
}
prepared_transfer_tx = self.conn.transactions.prepare(
operation = 'TRANSFER',
asset = transfer_asset,
inputs = transfer_input,
recipients = new_owner['public_key'],
metadata = ass_data
)
fulfilled_transfer_tx = self.conn.transactions.fulfill(
prepared_transfer_tx,
private_keys = prev_owner['private_key'],
)
print('BigChainConnector>> Asset prepared, signed and verified for submission')
self.conn.transactions.send_commit(fulfilled_transfer_tx)
txid = fulfilled_transfer_tx['id']
print('BigChainConnector>> Asset transfer committed to blockchain ledger with transaction id: ' + txid)
resp = {
'asset_id': asset_id,
'trans_id': txid,
'status_code': 200
}
return resp
def getAssetBlockInLedger(self, trans_id, trans_type=None):
# if block_height is None then either trans does not exist,
# invalid or simply queued - so not processed yet.
block_height = self.conn.blocks.get(txid=trans_id)
if block_height:
return self.conn.blocks.retrieve(str(block_height))
return None
def getAssetTransactions(self, asset_id, asset_type=None, trans_type=None):
#TODO use query data
return self.conn.transactions.get(asset_id = asset_id)
def getAsset(self, asset_id, asset_type=None):
data = self.conn.transactions.get(asset_id = asset_id, operation = 'CREATE')
return data[0]['asset']['data']
def getAssetMutableData(self, asset_id, asset_type=None):
#limit not supported
data = self.conn.transactions.get(asset_id = asset_id)
ml = []
for m in data:
ml.append(m['metadata'])
return ml
def getAssetOwnership(self, asset_id, asset_type=None):
#limit not supported
data = self.conn.transactions.get(asset_id=asset_id)
ml = []
for m in data:
obj = dict()
obj['trans_id'] = m['id']
obj['operation'] = m['operation']
obj['owners_before'] = m['inputs'][0]['owners_before']
obj['current_owners'] = m['outputs'][0]['public_keys']
ml.append(obj)
return ml