def main(): bdb_root_url = 'http://34.101.231.183:9984/' bdb = BigchainDB(bdb_root_url) alice = generate_keypair() bob = generate_keypair() # contoh asset data untuk block id_number = input("Masukkan nomor nomor id: ") patient_name = input("Masukkan nama pasien: ") symptoms = input("Masukkan gejala: ") division = input("Masukkan divisi RS: ") medication = input("Masukkan resep obat: ") comment = input("(Opsional) Masukkan Komentar: ") patient_data = { 'data': { 'patient': { 'id_number': id_number, 'patient_name': patient_name, 'symptoms': symptoms, 'division': division, 'medication': medication }, }, } # contoh metadata untuk asset block metadata = {'comment': comment} create_transaction(bdb, patient_data, metadata, alice)
def crear_usuarios(): users = [] users.append(generate_keypair()) users.append(generate_keypair()) users.append(generate_keypair()) users.append(generate_keypair()) return users
def sensor_by_id(sensor_id): if request.method == 'POST': print(json.loads(request.get_data())) # curl -d "{'temp':'30'}" -H "Content-Type: application/json" -X POST http://localhost:500 alice, bob = generate_keypair(), generate_keypair() print(alice, bob) for singleReading in json.loads(request.get_data()): bicycle_asset = {'data': singleReading} prepared_creation_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset=bicycle_asset) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) sent_creation_tx = bdb.transactions.send_commit( fulfilled_creation_tx) return request.get_data() else: limit = int(request.args.get('limit')) print("limit is {}".format(limit)) readings = [] for index, reading in enumerate( collection.find({ "data.entity": "reading", "data.resource_id": sensor_id }).limit(1).sort('data.Date', DESCENDING)): if index == limit: break readings.append(reading['data']) # try: print(readings) return json.dumps({"result": {"records": readings}})
def __init__(self): tokens = {} tokens['app_id'] = '764af86d' tokens['app_key'] = 'e416ddf812ab8b6196bc772280e7bea5' self.bdb = BigchainDB('https://test.ipdb.io', headers=tokens) self.alice = generate_keypair() self.bob = generate_keypair()
def altaUsuarios(): darth_vader = generate_keypair() bbdd.insertarUsuario("Darth vader", darth_vader[0], darth_vader[1]) boba_fett = generate_keypair() bbdd.insertarUsuario("Boba fett", boba_fett[0], boba_fett[1]) greedo = generate_keypair() bbdd.insertarUsuario("Greedo", greedo[0], greedo[1]) din_djarin = generate_keypair() bbdd.insertarUsuario("Din D jarin", din_djarin[0], din_djarin[1]) return render_template("todo.html")
def helloWorld(): alice, bob = generate_keypair(), generate_keypair() bicycle_asset = {'data': {'message': 'hello'}} prepared_creation_tx = bdb.transactions.prepare(operation='CREATE', signers=alice.public_key, asset=bicycle_asset) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) sent_creation_tx = bdb.transactions.send_commit(fulfilled_creation_tx) return 'hello {}'.format(sent_creation_tx)
def test(self): import time bc_db = BigchainInterface("http://kyber.ipdb.foundation", 80) def check_tx(txid): trials = 0 while trials < 60: try: if bc_db.conn.transactions.status(txid).get( 'status') == 'valid': print('Tx valid in:', trials, 'secs') break except bigchaindb_driver.exceptions.NotFoundError: trials += 1 time.sleep(1) identity = CryptoKeypair( "3P7GQqgPFv4EtuSxUKfynnsGRFaiqDs5yiesPGPXWN48", "HuXxaCfYmqxJGxf3o2cK51XFvE7hqYiurZfdky3VeMZD") debt_identity = CryptoKeypair( "4JqJ118C31Dy6VbG8CR7NaGGvh2jufuvB2QY9QKuMiWD", "6Ew2xojsYk4363hgBWM4JGGckqpQbwUfvUc6XvdSD7jD") identity = generate_keypair() debt_identity = generate_keypair() print(debt_identity) wallet = TokenWallet(bc_db, identity=identity) debt_wallet = TokenWallet(bc_db, identity=debt_identity) token = { "data": { "script": "if len(bigchain.get_outputs_filtered('{}', True)) > 0: raise". format(debt_identity.public_key) } } txid = wallet.issue(token) check_tx(txid) txid = debt_wallet.issue({"data": {"script": "if False: raise"}}) check_tx(txid) print("ok") try: txid = wallet.issue(token) check_tx(txid) except: pass
def __init__(self, user_list): global transaction_id self.bdb = BigchainDB(bdb_root_url) self.initializer = generate_keypair() self.users = {} self.currency_token = { 'data': { 'token_for': { 'currency': { 'serial_number': 'LR35902' } }, 'description': 'Time share token. Each token equals one hour of usage.', }, } create_receipents = [] user_key_list = [] self.transaction_id_dict = {} currency_metadata = "currencyTransaction :" for u in user_list: self.users[u] = generate_keypair() currency_metadata += u + "=" + str(100) + "," create_receipents.append(([self.users[u].public_key], 100)) user_key_list.append(self.users[u].public_key) self.transaction_id_dict[u] = transaction_id transaction_id += 1 metadata = {'metadata': currency_metadata} prepared_token_tx = self.bdb.transactions.prepare( operation='CREATE', signers=self.initializer.public_key, metadata=metadata, recipients=create_receipents, # recipients=[(user_key_list, 100)], asset=self.currency_token) self.recepients = create_receipents fulfilled_token_tx = self.bdb.transactions.fulfill( prepared_token_tx, private_keys=self.initializer.private_key) self.bdb.transactions.send_commit(fulfilled_token_tx) self.transfer_asset = {'id': fulfilled_token_tx['id']} self.asset = self.transfer_asset # self.transfer_asset = {'id': prepared_token_tx['id']} # self.output_index = 3 # self.output = fulfilled_token_tx['outputs'][self.output_index] self.output = fulfilled_token_tx['outputs']
def sensor(): print(request) print(json.loads(request.get_data())) # curl -d "{'temp':'30'}" -H "Content-Type: application/json" -X POST http://localhost:500 alice, bob = generate_keypair(), generate_keypair() bicycle_asset = {'data': json.loads(request.get_data())} prepared_creation_tx = bdb.transactions.prepare(operation='CREATE', signers=alice.public_key, asset=bicycle_asset) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) sent_creation_tx = bdb.transactions.send_commit(fulfilled_creation_tx) return request.get_data()
def create_keypair(data): # TODO Remove this if not DEMO if not data["keypair"]: keypair = generate_keypair() # TODO Remove this if not DEMO elif not data["keypair"]["public"] or not data["keypair"]["private"]: keypair = generate_keypair() print("Non valid keychain; new one is created for DEMO") else: keypair = data["keypair"] return keypair
def erisfyIt(pubKey): flag = -1 pubNDpriv = [] pubKey = hashIt(pubKey) #ErisPubKeys IS the name of the files ErisPubKeys = getPubKeysEris() for i in range(len(ErisPubKeys)): if ErisPubKeys[i] == (pubKey + ".txt"): flag = i if flag == -1: #make the user in bigchain alice = generate_keypair() priv1 = alice.signing_key pub1 = alice.verifying_key print("test private: " + priv1) print("test public: " + pub1) priv1 = encrypt_val(priv1) pub1 = encrypt_val(pub1) print(decrypt_val(priv1)) print(decrypt_val(pub1)) # index = len(BigchainPubKeys) createFile(pubKey, pub1, priv1) #BigchainPubKeys.append(pub1) #BigchainPrivKeys.append(priv1) #ErisPubKeys.append(pubKey) pubNDpriv = [decrypt_val(pub1), decrypt_val(priv1)] else: pubNDpriv = [getPubKeyBigchain(pubKey), getPrivKeyBigchain(pubKey)] return pubNDpriv
def main(): # Conecta ao nó de teste do BigchainDB bdb = BigchainDB('https://test.bigchaindb.com') # Gera o par de chaves para o sistema gravar as informações no banco de dados Blockchain evoting = generate_keypair() eleitores = get_eleitores() votos_computados = [] for i in range(0, len(eleitores) - 1): voto = bdb.transactions.prepare(operation='CREATE', signers=evoting.public_key, asset={ 'data': { 'id': eleitores[i]['id'], 'nome': eleitores[i]['nome'], 'voto': eleitores[i]['voto'] } }) voto_assinado = bdb.transactions.fulfill( voto, private_keys=evoting.private_key) voto_enviado = bdb.transactions.send_commit(voto_assinado) votos_computados.append(voto_enviado) # Imprime as informações gravadas no banco de dados Blockchain print(json.dumps(votos_computados, sort_keys=True, indent=4))
def execute_create_bid(): print(session['dept_id'], session['dept_publicKey'], session['dept_privateKey']) data = { 'data': { 'profile': { "seller_id": randint(1, 9999999999), "seller_name": request.form['seller-name'], "seller_city": request.form['seller-city'], "seller_state": request.form['seller-state'], "seller_publicKey": new_user.public_key, }, }, } from bigchaindb_driver.crypto import generate_keypair new_user = generate_keypair() prepared_token_tx = bdb.transactions.prepare(operation='CREATE', signers=new_user.public_key, asset=data, metadata={"test": "true"}) fulfilled_token_tx = bdb.transactions.fulfill( prepared_token_tx, private_keys=new_user.private_key) bdb.transactions.send_commit(fulfilled_token_tx)
def submit_transaction(self, invoice, metadata): # Generate a public/private keys. Unique for each transaction generate_customer_keys = generate_keypair() prepared_creation_tx = self.bdb.transactions.prepare( operation='CREATE', signers=generate_customer_keys.public_key, asset=invoice, metadata=metadata) fulfilled_creation_tx = self.bdb.transactions.fulfill( prepared_creation_tx, private_keys=generate_customer_keys.private_key) sent_creation_tx = self.bdb.transactions.send(fulfilled_creation_tx) current_txid = sent_creation_tx['id'] # Query, if the transaction is valid or not. i = 0 while i < 100: i += 1 try: if self.bdb.transactions.status(current_txid).get( 'status') == 'valid': break except bigchaindb_driver.exceptions.NotFoundError: pass try: status = self.bdb.transactions.status(current_txid).get('status') if status == "valid": return current_txid except NotFoundError as e: # In future we can have error codes such as ERR-INVALID_TX-400 etc. self.logger.error('Transaction "%s" Status.', current_txid, extra={'status': e.status_code}) return None
def test_generate_keypair(): from bigchaindb_driver.crypto import CryptoKeypair, generate_keypair keypair = generate_keypair() assert len(keypair) == 2 assert isinstance(keypair, CryptoKeypair) assert isinstance(keypair.private_key, str) assert isinstance(keypair.public_key, str)
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 test_double_create(): bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) alice = generate_keypair() results = queue.Queue() tx = bdb.transactions.fulfill( bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset={'data': {'uuid': str(uuid4())}}), private_keys=alice.private_key) def send_and_queue(tx): try: bdb.transactions.send_commit(tx) results.put('OK') except bigchaindb_driver.exceptions.TransportError as e: results.put('FAIL') t1 = Thread(target=send_and_queue, args=(tx, )) t2 = Thread(target=send_and_queue, args=(tx, )) t1.start() t2.start() results = [results.get(timeout=2), results.get(timeout=2)] assert results.count('OK') == 1 assert results.count('FAIL') == 1
def make_voter(voter_num, poll_id): voter_dict = {'voter_ids': {}, 'signing_keys': {}} # id:private for i in range(0, voter_num): ballot = { 'data': { 'vote': { 'poll_id': poll_id, 'serial': i, 'time_stamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }, }, } metadata = {'poll_id': poll_id} temp = generate_keypair() prepared_creation_tx = bdb.transactions.prepare( operation='CREATE', owners_before=temp.verifying_key, asset=ballot, metadata=metadata, ) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=temp.signing_key) sent_creation_tx = bdb.transactions.send(fulfilled_creation_tx) voter_dict['voter_ids'][i] = sent_creation_tx[ 'id'] # Voter asset creation id voter_dict['signing_keys'][ i] = temp.signing_key # private key for login del temp, prepared_creation_tx, fulfilled_creation_tx, sent_creation_tx # Delete temp variable for security reasons time.sleep(delay) # Cannot handle multiple votes in same timestamp return voter_dict
def create_seller_id(): from bigchaindb_driver.crypto import generate_keypair new_user = generate_keypair() acc_data = { 'data': { 'profile': { "seller_id": randint(1, 9999999999), "seller_name": request.form['seller-name'], "seller_city": request.form['seller-city'], "seller_state": request.form['seller-state'], "seller_publicKey": new_user.public_key, }, }, } prepared_token_tx = bdb.transactions.prepare( operation='CREATE', signers=new_user.public_key, asset=acc_data, metadata={ "test": "true" }) fulfilled_token_tx = bdb.transactions.fulfill( prepared_token_tx, private_keys=new_user.private_key) bdb.transactions.send_commit(fulfilled_token_tx) acc_data['data']['profile']['seller_privateKey'] = new_user.private_key db.sellers.insert(acc_data['data']['profile']) return redirect(url_for('dashboard'))
def add_block(data): bdb_root_url = 'https://test.bigchaindb.com' bdb = BigchainDB(bdb_root_url) alice = generate_keypair() # data = {'data': # {'123abc': # { # 'question': '1', # 'text': 'bkfabdcfreferfejfbewjuhcbwdichbewidyewbdiew ieydvewudhew eduew utvewboiugy ewduie', # 'marks': 0.35, # }, # }, # } prepared_creation_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset=data, ) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) sent_creation_tx = bdb.transactions.send_commit(fulfilled_creation_tx) block_height = bdb.blocks.get(txid=sent_creation_tx['id']) block = bdb.blocks.retrieve(str(block_height)) # print() print(block['transactions'][0].get('asset').get('data'))
def user_reg(request): user_form = UserForm profile_form = ProfileForm data = {'user_form': user_form, 'profile_form': profile_form} if request.method == 'POST': user_form = UserForm(request.POST) profile_form = ProfileForm(request.POST) data['user_form'] = user_form data['profile_form'] = profile_form if user_form.is_valid() and profile_form.is_valid(): user = user_form.save(commit=False) password = user_form.cleaned_data['password'] user.set_password(password) user_form.save() profile = profile_form.save(commit=False) profile.user = user keys = generate_keypair() profile.public_key = keys.public_key profile.private_key = keys.private_key profile.save() return redirect('../user_login') else: data['form_errors'] = 'Invalid Form' return render(request, 'user/register.html', data) else: return render(request, 'user/register.html', data)
def closure(use_canonical_key=None): bdb = BigchainDB() if use_canonical_key: alice = SimpleNamespace( private_key=b58encode(use_canonical_key[0]).decode(), public_key=b58encode(use_canonical_key[1][1:]).decode()) else: alice = generate_keypair() prepared_creation_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset={ 'data': { 'bicycle': { 'serial_number': ''.join(random.sample(string.hexdigits, 20)), 'manufacturer': 'bkfab', }, }, }, metadata={'planet': 'earth'}, ) fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) return fulfilled_creation_tx
def create_govt_dept(): from bigchaindb_driver.crypto import generate_keypair new_user = generate_keypair() acc_data = { 'data': { 'profile': { "dept_id": randint(1, 9999999999), "dept_name": request.form['dept-name'], "dept_city": request.form['dept-city'], "dept_state": request.form['dept-state'], "dept_publicKey": new_user.public_key, }, }, } prepared_token_tx = bdb.transactions.prepare( operation='CREATE', signers=new_user.public_key, asset=acc_data, metadata={ "test": "true" }) fulfilled_token_tx = bdb.transactions.fulfill( prepared_token_tx, private_keys=new_user.private_key) bdb.transactions.send_commit(fulfilled_token_tx) acc_data['data']['profile']['dept_privateKey'] = new_user.private_key db.dept.insert(acc_data['data']['profile']) return 'done'
def test_double_create(): bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) alice = generate_keypair() results = queue.Queue() tx = bdb.transactions.fulfill( bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset={'data': {'uuid': str(uuid4())}}), private_keys=alice.private_key) def send_and_queue(tx): try: bdb.transactions.send(tx) results.put('OK') except bigchaindb_driver.exceptions.TransportError as e: results.put('FAIL') t1 = Thread(target=send_and_queue, args=(tx, )) t2 = Thread(target=send_and_queue, args=(tx, )) t1.start() t2.start() results = [results.get(timeout=2), results.get(timeout=2)] assert results.count('OK') == 1 assert results.count('FAIL') == 1
def generate_key(): _result_msg = "done" _userkey = "" _public_key = "" _private_key = "" _jsonData = request.get_json() user_agent = request.headers.get('User-Agent', "") if type(_jsonData) is str: _jsonData = json.loads(request.get_json()) _username = _jsonData['username'] _userpassword = _jsonData['userpassword'] try: mydb = pymysql.connect(**setting.mysql_config) dbcursor = mydb.cursor() sql_str = """SELECT * FROM %s.user WHERE name = '%s'; """ % ( setting.mysql_db_name, _username) _mysql_rst = dbcursor.execute(sql_str) _mysql_result = dbcursor.fetchall() if _mysql_rst > 0: _result_msg = "That username is already in use!" else: _datetime = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") _salt = crypt.mksalt(crypt.METHOD_SHA512) _hash = crypt.crypt( "%s_%s_%s" % (_username, _userpassword, _datetime), _salt) _userkey_bytes = base64.b64encode( ('%s' % (_hash)).encode(encoding="utf-8")) _userkey = str(_userkey_bytes, encoding="utf-8") _keypair_chaindb = generate_keypair() _public_key = _keypair_chaindb.public_key _private_key = _keypair_chaindb.private_key _lastlogin = _datetime sql_str = """insert into %s.user(user.name,user.password,user.key,user.public_key,user.private_key,user.salt,user.generate_date,user.lastlogin_date) values ('%s','%s','%s','%s','%s','%s','%s','%s');""" % ( setting.mysql_db_name, _username, _userpassword, _userkey, _public_key, _private_key, _salt, _datetime, _lastlogin) _mysql_rst = dbcursor.execute(sql_str) mydb.commit() _result_msg = "generate_key done" except Exception as e: _result_msg = e _userkey = "" finally: mydb.close() _resultDict = dict(msg=("%s") % (_result_msg), user_key=_userkey) return _resultDict
def create_user(self, user_name): if self.user.keys(): return {"success": False, "message": "User exists"} user = generate_keypair() self.user = { 'pub.key': user.public_key, 'priv.key': user.private_key, 'name': user_name, 'user_type': None } with open(self.keydir / 'pub.key', 'w') as f: f.write(user.public_key) with open(self.keydir / 'priv.key', 'w') as f: f.write(user.private_key) try: result = self.transactionHelper.create_asset( user, { 'data': { 'type': "CREATE_USER", 'key': user.public_key, 'name': user_name } }) return {"success": True, "data": result} except MissingPrivateKeyError: return {"success": False, "message": "Invalid User"}
def make_voter(voter_num, poll_id): voter_dict = {'voter_ids': {}, 'signing_keys': {}} # id:private for i in range(0, voter_num): ballot = { 'data': { 'vote': { 'poll_id': poll_id, 'serial': i, 'time_stamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") }, }, } temp = generate_keypair() temp_ballot = bdb.transactions.create( verifying_key=temp. verifying_key, # Create Ballots before transaction signing_key=temp.signing_key, asset=ballot) # voter hold ballot voter_dict['voter_ids'][i] = temp_ballot[ 'id'] # Voter asset creation id voter_dict['signing_keys'][ i] = temp.signing_key # private key for login del temp, temp_ballot # Delete temp variable for security reasons time.sleep(delay) # Cannot handle multiple votes in same timestamp return voter_dict
def set_up(self): keys = generate_keypair() self.bigchaindb.admin = {'public': keys.public_key, 'private': keys.private_key} self.save_keys(self.bigchaindb.admin, 'administrator', 'admin') # setup app-asset, admin-asset and admin-instance self.bigchaindb.app_id, self.bigchaindb.admin_grp_id = self.bigchaindb.set_up_admin_role() # if setup was successful, save id if self.bigchaindb.app_id is not None: self.save_types(self.bigchaindb.app_id, 'app') # if setup was successful, save id if self.bigchaindb.admin_grp_id is not None: self.save_types(self.bigchaindb.admin_grp_id, 'admin') # create admin user self.bigchaindb.create_user('administrator', 'admin', self.bigchaindb.admin['public'], None) # setup user-group-assets notar_type, nachlass_type = self.bigchaindb.set_up_types() # if setup was successful, save id if notar_type is not None: self.save_types(notar_type, 'notar') # if setup was successful, save id if nachlass_type is not None: self.save_types(nachlass_type, 'nachlassgericht') # set up testament type-asset testament_type = self.bigchaindb.set_up_testament_type() if testament_type is not None: self.save_types(testament_type, 'testament')
def generate_keypair(self, seed=None): if seed: sk = nacl.signing.SigningKey(seed=seed) self.kp = CryptoKeypair( sk.encode(encoder=Base58Encoder).decode(), sk.verify_key.encode(encoder=Base58Encoder).decode()) else: self.kp = generate_keypair()
def create(): #context = create_context('secp256k1') #private_key = context.new_random_private_key() #signer = CryptoFactory(context).new_signer(private_key) key_pair = generate_keypair() return { 'pub_key': key_pair.public_key, 'priv_key': key_pair.private_key }
def __init__(self, app=None): self.bigchain = BigchainDB(BaseConfig.BIGCHAINDB__URL) keypair = generate_keypair() print('keypair', keypair) self.logger = None if app: self.init_app(app)
def send_naughty_tx(asset, metadata): # ## Set up a connection to BigchainDB # Check [test_basic.py](./test_basic.html) to get some more details # about the endpoint. bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) # Here's Alice. alice = generate_keypair() # Alice is in a naughty mood today, so she creates a tx with some naughty strings prepared_transaction = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset=asset, metadata=metadata) # She fulfills the transaction fulfilled_transaction = bdb.transactions.fulfill( prepared_transaction, private_keys=alice.private_key) # The fulfilled tx gets sent to the BDB network try: sent_transaction = bdb.transactions.send(fulfilled_transaction) except BadRequest as e: sent_transaction = e # If her key contained a '.', began with a '$', or contained a NUL character regex = '.*\..*|\$.*|.*\x00.*' key = next(iter(metadata)) if re.match(regex, key): # Then she expects a nicely formatted error code status_code = sent_transaction.status_code error = sent_transaction.error regex = '\{"message":"Invalid transaction \\(ValidationError\\): Invalid key name .* in asset object. ' \ 'The key name cannot contain characters .* or null characters","status":400\}\n' assert status_code == 400 assert re.fullmatch(regex, error), sent_transaction # Otherwise, she expects to see her transaction in the database elif 'id' in sent_transaction.keys(): tx_id = sent_transaction['id'] assert bdb.transactions.retrieve(tx_id) # If neither condition was true, then something weird happened... else: raise TypeError(sent_transaction)
def test_divisible_assets(): # ## Set up a connection to BigchainDB # Check [test_basic.py](./test_basic.html) to get some more details # about the endpoint. bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) # Oh look, it is Alice again and she brought her friend Bob along. alice, bob = generate_keypair(), generate_keypair() # ## Alice creates a time sharing token # Alice wants to go on vacation, while Bobs bike just broke down. # Alice decides to rent her bike to Bob while she is gone. # So she prepares a `CREATE` transaction to issues 10 tokens. # First, she prepares an asset for a time sharing token. As you can see in # the description, Bob and Alice agree that each token can be used to ride # the bike for one hour. bike_token = { 'data': { 'token_for': { 'bike': { 'serial_number': 420420 } }, 'description': 'Time share token. Each token equals one hour of riding.', }, } # She prepares a `CREATE` transaction and issues 10 tokens. # Here, Alice defines in a tuple that she wants to assign # these 10 tokens to Bob. prepared_token_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, recipients=[([bob.public_key], 10)], asset=bike_token) # She fulfills and sends the transaction. fulfilled_token_tx = bdb.transactions.fulfill( prepared_token_tx, private_keys=alice.private_key) bdb.transactions.send(fulfilled_token_tx, mode='commit') # We store the `id` of the transaction to use it later on. bike_token_id = fulfilled_token_tx['id'] # Let's check if the transaction was successful. assert bdb.transactions.retrieve(bike_token_id), \ 'Cannot find transaction {}'.format(bike_token_id) # Bob owns 10 tokens now. assert bdb.transactions.retrieve(bike_token_id)['outputs'][0][ 'amount'] == '10' # ## Bob wants to use the bike # Now that Bob got the tokens and the sun is shining, he wants to get out # with the bike for three hours. # To use the bike he has to send the tokens back to Alice. # To learn about the details of transferring a transaction check out # [test_basic.py](./test_basic.html) transfer_asset = {'id': bike_token_id} output_index = 0 output = fulfilled_token_tx['outputs'][output_index] transfer_input = {'fulfillment': output['condition']['details'], 'fulfills': {'output_index': output_index, 'transaction_id': fulfilled_token_tx[ 'id']}, 'owners_before': output['public_keys']} # To use the tokens Bob has to reassign 7 tokens to himself and the # amount he wants to use to Alice. prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=[([alice.public_key], 3), ([bob.public_key], 7)]) # He signs and sends the transaction. fulfilled_transfer_tx = bdb.transactions.fulfill( prepared_transfer_tx, private_keys=bob.private_key) sent_transfer_tx = bdb.transactions.send(fulfilled_transfer_tx, mode='commit') # First, Bob checks if the transaction was successful. assert bdb.transactions.retrieve( fulfilled_transfer_tx['id']) == sent_transfer_tx # There are two outputs in the transaction now. # The first output shows that Alice got back 3 tokens... assert bdb.transactions.retrieve( fulfilled_transfer_tx['id'])['outputs'][0]['amount'] == '3' # ... while Bob still has 7 left. assert bdb.transactions.retrieve( fulfilled_transfer_tx['id'])['outputs'][1]['amount'] == '7' # ## Bob wants to ride the bike again # It's been a week and Bob wants to right the bike again. # Now he wants to ride for 8 hours, that's a lot Bob! # He prepares the transaction again. transfer_asset = {'id': bike_token_id} # This time we need an `output_index` of 1, since we have two outputs # in the `fulfilled_transfer_tx` we created before. The first output with # index 0 is for Alice and the second output is for Bob. # Since Bob wants to spend more of his tokens he has to provide the # correct output with the correct amount of tokens. output_index = 1 output = fulfilled_transfer_tx['outputs'][output_index] transfer_input = {'fulfillment': output['condition']['details'], 'fulfills': {'output_index': output_index, 'transaction_id': fulfilled_transfer_tx['id']}, 'owners_before': output['public_keys']} # This time Bob only provides Alice in the `recipients` because he wants # to spend all his tokens prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=[([alice.public_key], 8)]) fulfilled_transfer_tx = bdb.transactions.fulfill( prepared_transfer_tx, private_keys=bob.private_key) # Oh Bob, what have you done?! You tried to spend more tokens than you had. # Remember Bob, last time you spent 3 tokens already, # so you only have 7 left. with pytest.raises(BadRequest) as error: bdb.transactions.send(fulfilled_transfer_tx, mode='commit') # Now Bob gets an error saying that the amount he wanted to spent is # higher than the amount of tokens he has left. assert error.value.args[0] == 400 message = 'Invalid transaction (AmountError): The amount used in the ' \ 'inputs `7` needs to be same as the amount used in the ' \ 'outputs `8`' assert error.value.args[2]['message'] == message
def test_basic(): # ## Set up a connection to BigchainDB # To use BighainDB we need a connection. Here we create one. By default we # connect to localhost, but you can override this value using the env variable # called `BIGCHAINDB_ENDPOINT`, a valid value must include the schema: # `https://example.com:9984` bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) # ## Create keypairs # This test requires the interaction between two actors with their own keypair. # The two keypairs will be called—drum roll—Alice and Bob. alice, bob = generate_keypair(), generate_keypair() # ## Alice registers her bike in BigchainDB # Alice has a nice bike, and here she creates the "digital twin" # of her bike. bike = {'data': {'bicycle': {'serial_number': 420420}}} # She prepares a `CREATE` transaction... prepared_creation_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset=bike) # ... and she fulfills it with her private key. fulfilled_creation_tx = bdb.transactions.fulfill( prepared_creation_tx, private_keys=alice.private_key) # We will use the `id` of this transaction several time, so we store it in # a variable with a short and easy name bike_id = fulfilled_creation_tx['id'] # Now she is ready to send it to the BigchainDB Network. sent_transfer_tx = bdb.transactions.send(fulfilled_creation_tx) # And just to be 100% sure, she also checks if she can retrieve # it from the BigchainDB node. assert bdb.transactions.retrieve(bike_id), 'Cannot find transaction {}'.format(bike_id) # Alice is now the proud owner of one unspent asset. assert len(bdb.outputs.get(alice.public_key, spent=False)) == 1 assert bdb.outputs.get(alice.public_key)[0]['transaction_id'] == bike_id # ## Alice transfers her bike to Bob # After registering her bike, Alice is ready to transfer it to Bob. # She needs to create a new `TRANSFER` transaction. # A `TRANSFER` transaction contains a pointer to the original asset. The original asset # is identified by the `id` of the `CREATE` transaction that defined it. transfer_asset = {'id': bike_id} # Alice wants to spend the one and only output available, the one with index `0`. output_index = 0 output = fulfilled_creation_tx['outputs'][output_index] # Here, she defines the `input` of the `TRANSFER` transaction. The `input` contains # several keys: # # - `fulfillment`, taken from the previous `CREATE` transaction. # - `fulfills`, that specifies which condition she is fulfilling. # - `owners_before`. transfer_input = {'fulfillment': output['condition']['details'], 'fulfills': {'output_index': output_index, 'transaction_id': fulfilled_creation_tx['id']}, 'owners_before': output['public_keys']} # Now that all the elements are set, she creates the actual transaction... prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=bob.public_key) # ... and signs it with her private key. fulfilled_transfer_tx = bdb.transactions.fulfill( prepared_transfer_tx, private_keys=alice.private_key) # She finally sends the transaction to a BigchainDB node. sent_transfer_tx = bdb.transactions.send(fulfilled_transfer_tx) # And just to be 100% sure, she also checks if she can retrieve # it from the BigchainDB node. assert bdb.transactions.retrieve(fulfilled_transfer_tx['id']) == sent_transfer_tx # Now Alice has zero unspent transactions. assert len(bdb.outputs.get(alice.public_key, spent=False)) == 0 # While Bob has one. assert len(bdb.outputs.get(bob.public_key, spent=False)) == 1 # Bob double checks what he got was the actual bike. bob_tx_id = bdb.outputs.get(bob.public_key, spent=False)[0]['transaction_id'] assert bdb.transactions.retrieve(bob_tx_id) == sent_transfer_tx
def test_multiple_owners(): # ## Set up a connection to BigchainDB # Check [test_basic.py](./test_basic.html) to get some more details # about the endpoint. bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) # Hey Alice and Bob, nice to see you again! alice, bob = generate_keypair(), generate_keypair() # ## Alice and Bob create a transaction # Alice and Bob just moved into a shared flat, no one can afford these # high rents anymore. Bob suggests to get a dish washer for the # kitchen. Alice agrees and here they go, creating the asset for their # dish washer. dw_asset = { 'data': { 'dish washer': { 'serial_number': 1337 } } } # They prepare a `CREATE` transaction. To have multiple owners, both # Bob and Alice need to be the recipients. prepared_dw_tx = bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, recipients=(alice.public_key, bob.public_key), asset=dw_asset) # Now they both sign the transaction by providing their private keys. # And send it afterwards. fulfilled_dw_tx = bdb.transactions.fulfill( prepared_dw_tx, private_keys=[alice.private_key, bob.private_key]) bdb.transactions.send_commit(fulfilled_dw_tx) # We store the `id` of the transaction to use it later on. dw_id = fulfilled_dw_tx['id'] # Let's check if the transaction was successful. assert bdb.transactions.retrieve(dw_id), \ 'Cannot find transaction {}'.format(dw_id) # The transaction should have two public keys in the outputs. assert len( bdb.transactions.retrieve(dw_id)['outputs'][0]['public_keys']) == 2 # ## Alice and Bob transfer a transaction to Carol. # Alice and Bob save a lot of money living together. They often go out # for dinner and don't cook at home. But now they don't have any dishes to # wash, so they decide to sell the dish washer to their friend Carol. # Hey Carol, nice to meet you! carol = generate_keypair() # Alice and Bob prepare the transaction to transfer the dish washer to # Carol. transfer_asset = {'id': dw_id} output_index = 0 output = fulfilled_dw_tx['outputs'][output_index] transfer_input = {'fulfillment': output['condition']['details'], 'fulfills': {'output_index': output_index, 'transaction_id': fulfilled_dw_tx[ 'id']}, 'owners_before': output['public_keys']} # Now they create the transaction... prepared_transfer_tx = bdb.transactions.prepare( operation='TRANSFER', asset=transfer_asset, inputs=transfer_input, recipients=carol.public_key) # ... and sign it with their private keys, then send it. fulfilled_transfer_tx = bdb.transactions.fulfill( prepared_transfer_tx, private_keys=[alice.private_key, bob.private_key]) sent_transfer_tx = bdb.transactions.send_commit(fulfilled_transfer_tx) # They check if the transaction was successful. assert bdb.transactions.retrieve( fulfilled_transfer_tx['id']) == sent_transfer_tx # The owners before should include both Alice and Bob. assert len( bdb.transactions.retrieve(fulfilled_transfer_tx['id'])['inputs'][0][ 'owners_before']) == 2 # While the new owner is Carol. assert bdb.transactions.retrieve(fulfilled_transfer_tx['id'])[ 'outputs'][0]['public_keys'][0] == carol.public_key
def test_stream(): # ## Set up the test # We use the env variable `BICHAINDB_ENDPOINT` to know where to connect. # Check [test_basic.py](./test_basic.html) for more information. BDB_ENDPOINT = os.environ.get('BIGCHAINDB_ENDPOINT') # *That's pretty bad, but let's do like this for now.* WS_ENDPOINT = 'ws://{}:9985/api/v1/streams/valid_transactions'.format(BDB_ENDPOINT.rsplit(':')[0]) bdb = BigchainDB(BDB_ENDPOINT) # Hello to Alice again, she is pretty active in those tests, good job # Alice! alice = generate_keypair() # We need few variables to keep the state, specifically we need `sent` to # keep track of all transactions Alice sent to BigchainDB, while `received` # are the transactions BigchainDB validated and sent back to her. sent = [] received = queue.Queue() # In this test we use a websocket. The websocket must be started **before** # sending transactions to BigchainDB, otherwise we might lose some # transactions. The `ws_ready` event is used to synchronize the main thread # with the listen thread. ws_ready = Event() # ## Listening to events # This is the function run by the complementary thread. def listen(): # First we connect to the remote endpoint using the WebSocket protocol. ws = create_connection(WS_ENDPOINT) # After the connection has been set up, we can signal the main thread # to proceed (continue reading, it should make sense in a second.) ws_ready.set() # It's time to consume all events coming from the BigchainDB stream API. # Every time a new event is received, it is put in the queue shared # with the main thread. while True: result = ws.recv() received.put(result) # Put `listen` in a thread, and start it. Note that `listen` is a local # function and it can access all variables in the enclosing function. t = Thread(target=listen, daemon=True) t.start() # ## Pushing the transactions to BigchainDB # After starting the listen thread, we wait for it to connect, and then we # proceed. ws_ready.wait() # Here we prepare, sign, and send ten different `CREATE` transactions. To # make sure each transaction is different from the other, we generate a # random `uuid`. for _ in range(10): tx = bdb.transactions.fulfill( bdb.transactions.prepare( operation='CREATE', signers=alice.public_key, asset={'data': {'uuid': str(uuid4())}}), private_keys=alice.private_key) # We don't want to wait for each transaction to be in a block. By using # `async` mode, we make sure that the driver returns as soon as the # transaction is pushed to the BigchainDB API. Remember: we expect all # transactions to be in the shared queue: this is a two phase test, # first we send a bunch of transactions, then we check if they are # valid (and, in this case, they should). bdb.transactions.send_async(tx) # The `id` of every sent transaction is then stored in a list. sent.append(tx['id']) # ## Check the valid transactions coming from BigchainDB # Now we are ready to check if BigchainDB did its job. A simple way to # check if all sent transactions have been processed is to **remove** from # `sent` the transactions we get from the *listen thread*. At one point in # time, `sent` should be empty, and we exit the test. while sent: # To avoid waiting forever, we have an arbitrary timeout of 5 # seconds: it should be enough time for BigchainDB to create # blocks, in fact a new block is created every second. If we hit # the timeout, then game over ¯\\\_(ツ)\_/¯ try: event = received.get(timeout=5) txid = json.loads(event)['transaction_id'] except queue.Empty: assert False, 'Did not receive all expected transactions' # Last thing is to try to remove the `txid` from the set of sent # transactions. If this test is running in parallel with others, we # might get a transaction id of another test, and `remove` can fail. # It's OK if this happens. try: sent.remove(txid) except ValueError: pass