def spend_utxo(self, utxo_id, new_owner, amount, signer): """Creates a spending transaction and inserts it into the chain. Args: utxo_id (int): Identifier of the UTXO to spend. new_owner (EthereumAccount): Account to own the output of this spend. amount (int): Amount to spend. signer (EthereumAccount): Account to sign this transaction. Returns: int: Unique identifier of the spend. """ spend_tx = Transaction(*decode_utxo_id(utxo_id), 0, 0, 0, NULL_ADDRESS, new_owner.address, amount, NULL_ADDRESS, 0) spend_tx.sign1(signer.key) blknum = self.root_chain.currentChildBlock() block = Block(transaction_set=[spend_tx], number=blknum) block.sign(self.operator.key) self.root_chain.submitBlock(block.root) self.child_chain.add_block(block) return encode_utxo_id(blknum, 0, 0)
def set_dict(self, **num): print("set test") print("Data type of argument:", type(num)) for key, value in num.items(): print("{} is {}".format(key, value)) #self.root_chain.deposit(transact={'from': owner, 'value': amount}) mapping = {} mapping.update(num) for key, value in mapping.items(): print("{} is {}".format(key, value)) #convert dict to binary string bin_mapping = pickle.dumps(mapping) blknum = self.chain.next_deposit_block new_block = Block(None, blknum, NULL_SIGNATURE) new_block.add_mapping(mapping) self.chain.add_block(new_block) print("Number {} {}".format(new_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, 0, bin_mapping) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].mapping)) self.chain.set_dict(**num)
def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = {} self.tree = MerkleTree(2) self.roots = {} self.nullifiers = {} self.height = 0 self.current_block = Block()
def submit_block(self, block): if isinstance(block, str): block = rlp.decode(utils.decode_hex(block), Block) self.chain.add_block(block) self.root_chain.transact({ 'from': utils.checksum_encode(address_to_hex(self.operator)) }).submitBlock(block.merkle.root) self.current_block = Block(number=self.chain.next_child_block)
def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = Chain(self.operator) self.current_block = Block(number=self.chain.next_child_block) # Listen for events self.event_listener = RootEventListener(root_chain, confirmations=0) self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit)
class ChildChain(object): def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = Chain(self.operator) self.current_block = Block(number=self.chain.next_child_block) # Listen for events self.event_listener = RootEventListener(root_chain, confirmations=0) self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit) def apply_exit(self, event): event_args = event['args'] utxo_id = event_args['utxoPos'] self.chain.mark_utxo_spent(utxo_id) def apply_deposit(self, event): event_args = event['args'] owner = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = get_deposit_tx(owner, amount) deposit_block = Block([deposit_tx], number=blknum) self.chain.add_block(deposit_block) def apply_transaction(self, tx): self.chain.validate_transaction(tx, self.current_block.spent_utxos) self.current_block.add_transaction(tx) return encode_utxo_id(self.current_block.number, len(self.current_block.transaction_set) - 1, 0) def submit_block(self, block): self.chain.add_block(block) self.root_chain.transact({ 'from': self.operator }).submitBlock(block.merkle.root) self.current_block = Block(number=self.chain.next_child_block) def get_transaction(self, tx_id): return self.chain.get_transaction(tx_id) def get_block(self, blknum): return self.chain.get_block(blknum) def get_current_block(self): return self.current_block def get_all_blocks(self): for b in list(self.chain.blocks.values()): b.print_debug() return ""
class ChildChain(object): def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = Chain(self.operator) self.current_block = Block(number=self.chain.next_child_block) # Listen for events self.event_listener = RootEventListener(root_chain, confirmations=0) self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit) def apply_exit(self, event): event_args = event['args'] utxo_id = event_args['utxoPos'] self.chain.mark_utxo_spent(utxo_id) def apply_deposit(self, event): event_args = event['args'] owner = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = get_deposit_tx(owner, amount) deposit_block = Block([deposit_tx], number=blknum) self.chain.add_block(deposit_block) def apply_transaction(self, tx): self.chain.validate_transaction(tx, self.current_block.spent_utxos) self.current_block.add_transaction(tx) return encode_utxo_id(self.current_block.number, len(self.current_block.transaction_set) - 1, 0) def submit_block(self, block): if isinstance(block, str): block = rlp.decode(utils.decode_hex(block), Block) self.chain.add_block(block) self.root_chain.transact({ 'from': utils.checksum_encode(address_to_hex(self.operator)) }).submitBlock(block.merkle.root) self.current_block = Block(number=self.chain.next_child_block) def get_transaction(self, tx_id): return self.chain.get_transaction(tx_id) def get_block(self, blknum): return rlp.encode(self.chain.get_block(blknum), Block).hex() def get_current_block(self): return rlp.encode(self.current_block, Block).hex()
def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = Chain(self.operator) self.current_block = Block(number=self.chain.next_child_block) print("self.current_block {0}".format(self.current_block.number)) # Listen for events self.event_listener = RootEventListener(root_chain, confirmations=0) self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit) self.event_listener.on('MsgSender', self.msgsender) self.event_listener.on('FinalState', self.finalstate) self.event_listener.on('forDebug01', self.debug01)
def submit_block(self, transactions, signer=None, force_invalid=False): signer = signer or self.operator blknum = self.root_chain.nextChildBlock() block = Block(transactions, number=blknum) block.sign(signer.key) self.root_chain.submitBlock(block.root, sender=signer.key) if force_invalid: self.child_chain.blocks[self.child_chain.next_child_block] = block self.child_chain.next_deposit_block = self.child_chain.next_child_block + 1 self.child_chain.next_child_block += self.child_chain.child_block_interval else: assert self.child_chain.add_block(block) return blknum
def __init__(self, authority, root_chain): self.root_chain = root_chain self.authority = authority self.blocks = {} self.child_block_interval = 1000 self.current_block_number = self.child_block_interval self.current_block = Block() self.pending_transactions = [] self.event_listener = RootEventListener(root_chain, confirmations=0) # Register event listeners self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit)
def submit_block(self, block): block = rlp.decode(utils.decode_hex(block), Block) if block.merklize_transaction_set() != self.current_block.merklize_transaction_set(): raise InvalidBlockMerkleException('input block merkle mismatch with the current block') valid_signature = block.sig != NULL_SIGNATURE and block.sender == bytes.fromhex(self.authority[2:]) if not valid_signature: raise InvalidBlockSignatureException('failed to submit block') self.root_chain.transact({'from': self.authority}).submitBlock(block.merkle.root) # TODO: iterate through block and validate transactions self.blocks[self.current_block_number] = self.current_block self.current_block_number += self.child_block_interval self.current_block = Block()
def deposit_token(self, owner, token, amount): """Mints, approves and deposits token for given owner and amount Args: owner (EthereumAccount): Account to own the deposit. token (Contract: ERC20, MintableToken): Token to be deposited. amount (int): Deposit amount. Returns: int: Unique identifier of the deposit. """ deposit_tx = Transaction(outputs=[(owner.address, token.address, amount)]) token.mint(owner.address, amount) token.approve(self.root_chain.erc20_vault.address, amount, **{'from': owner.address}) blknum = self.root_chain.getDepositBlockNumber() pre_balance = self.get_balance(self.root_chain.erc20_vault, token) self.root_chain.depositFrom(deposit_tx.encoded, **{'from': owner.address}) balance = self.get_balance(self.root_chain.erc20_vault, token) assert balance == pre_balance + amount block = Block(transactions=[deposit_tx], number=blknum) self.child_chain.add_block(block) return encode_utxo_id(blknum, 0, 0)
def deposit_token(self, owner, token, amount): """Mints, approves and deposits token for given owner and amount Args: owner (EthereumAccount): Account to own the deposit. token (Contract: ERC20, MintableToken): Token to be deposited. amount (int): Deposit amount. Returns: int: Unique identifier of the deposit. """ deposit_tx = Transaction(0, 0, 0, 0, 0, 0, token.address, owner.address, amount, NULL_ADDRESS, 0) token.mint(owner.address, amount) self.ethtester.chain.mine() token.approve(self.root_chain.address, amount, sender=owner.key) self.ethtester.chain.mine() blknum = self.root_chain.getDepositBlock() self.root_chain.depositFrom(owner.address, token.address, amount, sender=owner.key) block = Block(transaction_set=[deposit_tx], number=blknum) self.child_chain.add_block(block) return blknum
def _deposit(testlang, owner, amount, blknum): deposit_tx = Transaction(outputs=[(owner.address, NULL_ADDRESS, amount)]) testlang.root_chain.eth_vault.functions.deposit(deposit_tx.encoded).transact({'from': owner.address, 'value': amount}) deposit_id = encode_utxo_id(blknum, 0, 0) block = Block([deposit_tx], number=blknum) testlang.child_chain.add_block(block) return deposit_id
def deposit(self, owner, amount): deposit_tx = Transaction(outputs=[(owner.address, NULL_ADDRESS, amount)]) blknum = self.root_chain.getDepositBlockNumber() self.root_chain.deposit(deposit_tx.encoded, value=amount) deposit_id = encode_utxo_id(blknum, 0, 0) block = Block([deposit_tx], number=blknum) self.child_chain.add_block(block) return deposit_id
def apply_deposit(self, event): event_args = event['args'] owner = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = get_deposit_tx(owner, amount) deposit_block = Block([deposit_tx], number=blknum) self.chain.add_block(deposit_block)
def test_commit_plasma_block_root_should_succeed(testlang): # Operator should be able to submit operator = testlang.accounts[0] block = Block() testlang.commit_plasma_block_root(block, signer=operator) # Check that the block was created correctly plasma_block_root = testlang.get_plasma_block(1) assert plasma_block_root.root == block.root assert plasma_block_root.timestamp == testlang.ethtester.chain.head_state.timestamp assert testlang.current_plasma_block_number == 2
def test_commit_plasma_block_root_not_operator_should_fail(testlang): # Operator should be able to submit non_operator = testlang.accounts[1] block = Block() with pytest.raises(TransactionFailed): testlang.commit_plasma_block_root(block, signer=non_operator) # Check nothing was submitted plasma_block = testlang.get_plasma_block(1) assert plasma_block.root == NULL_HASH assert plasma_block.timestamp == 0 assert testlang.current_plasma_block_number == 1
def apply_deposit(self, event): event_args = event['args'] depositor = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, depositor, amount, NULL_ADDRESS, 0) deposit_block = Block([deposit_tx]) self.blocks[blknum] = deposit_block
def deposit(self, owner, amount): """Creates a deposit transaction for a given owner and amount. Args: owner (EthereumAccount): Account to own the deposit. amount (int): Deposit amount. Returns: int: Unique identifier of the deposit. """ deposit_tx = Transaction(inputs=[], outputs=[(owner.address, amount)]) blknum = self.root_chain.currentPlasmaBlockNumber() self.root_chain.deposit(value=amount, sender=owner.key) block = Block(transactions=[deposit_tx], number=blknum) self.child_chain.add_block(block) return blknum
def deposit(self, owner, amount): """Creates a deposit transaction for a given owner and amount. Args: owner (EthereumAccount): Account to own the deposit. amount (int): Deposit amount. Returns: int: Unique identifier of the deposit. """ deposit_tx = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, owner.address, amount, NULL_ADDRESS, 0) blknum = self.root_chain.getDepositBlock() self.root_chain.deposit(value=amount, sender=owner.key) block = Block(transaction_set=[deposit_tx], number=blknum) self.child_chain.add_block(block) return blknum
def spend_utxo(self, utxo_position, new_owner, amount, signer): """Creates a spending transaction and inserts it into the chain. Args: utxo_position (int): Identifier of the UTXO to spend. new_owner (EthereumAccount): Account to own the output of this spend. amount (int): Amount to spend. signer (EthereumAccount): Account to sign this transaction. Returns: int: Unique identifier of the spend. """ spend_tx = Transaction(inputs=[decode_utxo_position(utxo_position)], outputs=[(new_owner.address, amount)]) spend_tx.sign(0, signer.key) blknum = self.root_chain.currentPlasmaBlockNumber() block = Block(transactions=[spend_tx], number=blknum) self.commit_plasma_block_root(block) return encode_utxo_position(blknum, 0, 0)
def set_test(self, num): print("set test") print("Data type of argument:", type(num)) blknum = self.chain.next_deposit_block file_block = Block(None, blknum, NULL_SIGNATURE) self.chain.add_block(file_block) print("Number {} {} {}".format(num, file_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, num) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].files)) self.chain.set_test(num)
def submit_block(self, block): self.chain.add_block(block) self.root_chain.transact({ 'from': self.operator }).submitBlock(block.merkle.root) self.current_block = Block(number=self.chain.next_child_block)
class ChildChain(object): def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = Chain(self.operator) self.current_block = Block(number=self.chain.next_child_block) print("self.current_block {0}".format(self.current_block.number)) # Listen for events self.event_listener = RootEventListener(root_chain, confirmations=0) self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit) self.event_listener.on('MsgSender', self.msgsender) self.event_listener.on('FinalState', self.finalstate) self.event_listener.on('forDebug01', self.debug01) def debug01(self, event): print("debug01 {0}".format(event['args'])) def finalstate(self, event): print("finalstate {0}".format(event['args'])) event_args = event['args'] dmapping = event_args['dmapping'] print("pickle {}".format(pickle.loads(dmapping))) def msgsender(self, event): print("msgsender {0}".format(event['args'])) def apply_exit(self, event): print("exit started {0}".format(event['args'])) event_args = event['args'] utxo_id = event_args['utxoPos'] blknum = utxo_id / 1000000000 print("blknum {0}".format(blknum)) block = self.chain.get_block(blknum) print("Files {}".format(block.transaction_set[0].files)) self.chain.mark_utxo_spent(utxo_id) def apply_deposit(self, event): print("apply deposit {0}".format(event['args'])) event_args = event['args'] owner = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = get_deposit_tx(owner, amount) deposit_block = Block([deposit_tx], number=blknum) self.chain.add_block(deposit_block) def apply_transaction(self, tx): print("spent_utxos {0} {1}".format(self.current_block.spent_utxos, self.current_block.number)) self.chain.validate_transaction(tx, self.current_block.spent_utxos) self.current_block.add_transaction(tx) return encode_utxo_id(self.current_block.number, len(self.current_block.transaction_set) - 1, 0) def submit_block(self, block): self.chain.add_block(block) self.root_chain.transact({ 'from': self.operator }).submitBlock(block.merkle.root) self.current_block = Block(number=self.chain.next_child_block) def get_transaction(self, tx_id): return self.chain.get_transaction(tx_id) def get_block(self, blknum): return self.chain.get_block(blknum) def get_current_block(self): print("current block") return self.current_block def get_current_block_num(self): print("current block num") return self.current_block.number def get_test(self): print("get test") return self.chain.get_test() def set_test(self, num): print("set test") print("Data type of argument:", type(num)) blknum = self.chain.next_deposit_block file_block = Block(None, blknum, NULL_SIGNATURE) self.chain.add_block(file_block) print("Number {} {} {}".format(num, file_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, num) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].files)) self.chain.set_test(num) def set_dict(self, **num): print("set test") print("Data type of argument:", type(num)) for key, value in num.items(): print("{} is {}".format(key, value)) #self.root_chain.deposit(transact={'from': owner, 'value': amount}) mapping = {} mapping.update(num) for key, value in mapping.items(): print("{} is {}".format(key, value)) #convert dict to binary string bin_mapping = pickle.dumps(mapping) blknum = self.chain.next_deposit_block new_block = Block(None, blknum, NULL_SIGNATURE) new_block.add_mapping(mapping) self.chain.add_block(new_block) print("Number {} {}".format(new_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, 0, bin_mapping) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].mapping)) self.chain.set_dict(**num) def hello(self): print("hello")
def block(): return Block()
def submit_block(self, block): self.chain[self.height] = block self.root_chain.submitBlock(self.operator, block.root) self.height += 1 self.current_block = Block(number=self.height)
class ChildChain(object): def __init__(self, authority, root_chain): self.root_chain = root_chain self.authority = authority self.blocks = {} self.child_block_interval = 1000 self.current_block_number = self.child_block_interval self.current_block = Block() self.pending_transactions = [] self.event_listener = RootEventListener(root_chain, confirmations=0) # Register event listeners self.event_listener.on('Deposit', self.apply_deposit) self.event_listener.on('ExitStarted', self.apply_exit) def apply_exit(self, event): event_args = event['args'] utxo_pos = event_args['utxoPos'] self.mark_utxo_spent(*decode_utxo_id(utxo_pos)) def apply_deposit(self, event): event_args = event['args'] depositor = event_args['depositor'] amount = event_args['amount'] blknum = event_args['depositBlock'] deposit_tx = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, depositor, amount, NULL_ADDRESS, 0) deposit_block = Block([deposit_tx]) self.blocks[blknum] = deposit_block def apply_transaction(self, transaction): tx = rlp.decode(utils.decode_hex(transaction), Transaction) # Validate the transaction self.validate_tx(tx) # Mark the inputs as spent self.mark_utxo_spent(tx.blknum1, tx.txindex1, tx.oindex1) self.mark_utxo_spent(tx.blknum2, tx.txindex2, tx.oindex2) self.current_block.transaction_set.append(tx) def validate_tx(self, tx): inputs = [(tx.blknum1, tx.txindex1, tx.oindex1), (tx.blknum2, tx.txindex2, tx.oindex2)] output_amount = tx.amount1 + tx.amount2 input_amount = 0 for (blknum, txindex, oindex) in inputs: # Assume empty inputs and are valid if blknum == 0: continue transaction = self.blocks[blknum].transaction_set[txindex] if oindex == 0: valid_signature = tx.sig1 != NULL_SIGNATURE and transaction.newowner1 == tx.sender1 spent = transaction.spent1 input_amount += transaction.amount1 else: valid_signature = tx.sig2 != NULL_SIGNATURE and transaction.newowner2 == tx.sender2 spent = transaction.spent2 input_amount += transaction.amount2 if spent: raise TxAlreadySpentException('failed to validate tx') if not valid_signature: raise InvalidTxSignatureException('failed to validate tx') if input_amount < output_amount: raise TxAmountMismatchException('failed to validate tx') def mark_utxo_spent(self, blknum, txindex, oindex): if blknum == 0: return if oindex == 0: self.blocks[blknum].transaction_set[txindex].spent1 = True else: self.blocks[blknum].transaction_set[txindex].spent2 = True def submit_block(self, block): block = rlp.decode(utils.decode_hex(block), Block) if block.merklize_transaction_set() != self.current_block.merklize_transaction_set(): raise InvalidBlockMerkleException('input block merkle mismatch with the current block') valid_signature = block.sig != NULL_SIGNATURE and block.sender == bytes.fromhex(self.authority[2:]) if not valid_signature: raise InvalidBlockSignatureException('failed to submit block') self.root_chain.transact({'from': self.authority}).submitBlock(block.merkle.root) # TODO: iterate through block and validate transactions self.blocks[self.current_block_number] = self.current_block self.current_block_number += self.child_block_interval self.current_block = Block() def get_transaction(self, blknum, txindex): return rlp.encode(self.blocks[blknum].transaction_set[txindex]).hex() def get_tx_pos(self, transaction): decoded_tx = rlp.decode(utils.decode_hex(transaction), Transaction) for blknum in self.blocks: block = self.blocks[blknum] for txindex in range(0, len(block.transaction_set)): tx = block.transaction_set[txindex] if (decoded_tx.hash == tx.hash): return blknum, txindex return None, None def get_block(self, blknum): return rlp.encode(self.blocks[blknum]).hex() def get_current_block(self): return rlp.encode(self.current_block).hex() def get_current_block_num(self): return self.current_block_number
class ChildChain(object): def __init__(self, operator, root_chain): self.operator = operator self.root_chain = root_chain self.chain = {} self.tree = MerkleTree(2) self.roots = {} self.nullifiers = {} self.height = 0 self.current_block = Block() def apply_exit(self): # TODO return def apply_deposit(self): # TODO return def apply_transaction(self, transaction): tx = Transaction(transaction["serialNumbers"], transaction["newRecords"], transaction["memo"], transaction["in_root"], transaction["in_proof"]) assert (self.approve_transaction(tx.serialNumbers, tx.newRecords, tx.memo, tx.in_root, tx.in_root)) # insert into tree for i in range(len(tx.newRecords)): self.insert(tx.newRecords[i]) print("Added new commitment: ", tx.newRecords[i]) print("Added new memo: ", tx.memo[i]) self.current_block.add(tx, self.get_root()) # For now, 1 tx = 1 block! self.submit_block(self.current_block) def submit_block(self, block): self.chain[self.height] = block self.root_chain.submitBlock(self.operator, block.root) self.height += 1 self.current_block = Block(number=self.height) def get_root(self): return self.tree.root def insert(self, leaf): # insert leaf to merkle tree self.tree.append(leaf) self.roots[self.get_root()] = True def is_spent(self, nullifier): # check if utxo is spent return self.nullifiers[nullifier] def approve_transaction(self, serialNumbers, newRecords, memo, in_root, in_proof): # verify transaction assert (len(newRecords) > 0) assert (len(newRecords) == len(memo)) assert (len(serialNumbers) > 0) # assert(self.roots[in_root]) is_valid = self.verify_proof(serialNumbers, newRecords, memo, in_root, in_proof) assert (is_valid) # check if record is dummy for sn in serialNumbers: # assert(self.nullifiers[sn]) self.nullifiers[sn] = True return True def verify_proof(self, serialNumbers, newRecords, memo, in_root, in_proof): # construct SNARK input snark_input = self.hash_public_inputs(serialNumbers, newRecords, memo, in_root) # return verifier.verify(self.vk, self.vk_gammaABC, in_proof, snark_input) return True def hash_public_inputs(self, serialNumbers, newRecords, memo, in_root): inputs_to_hash = [] for sn in serialNumbers: inputs_to_hash.append(int(sn)) for commit in newRecords: inputs_to_hash.append(int(commit)) for m in memo: inputs_to_hash.append(int(m)) inputs_to_hash.append(int(in_root)) return mimc_hash(inputs_to_hash)