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()
class AccountManager(object): def __init__(self, tree_size): self._accounts = [] self._key2idx = dict() self._tree = MerkleTree(tree_size) def lookup_accounts(self, *args): return [self.lookup_account(_) for _ in args] def lookup_account(self, index): if isinstance(index, AccountState): assert index.index is not None index = index.index elif isinstance(index, Point): index = self._key2idx[index] return self._accounts[index] def new_account(self, balance=0): secret, pubkey = eddsa_random_keypair() return secret, self.add_account(pubkey, balance) def add_account(self, pubkey, balance=0, nonce=0): assert isinstance(pubkey, Point) state = AccountState(pubkey, balance, nonce) state.index = self._tree.append(state.hash()) self._accounts.append(state) self._key2idx[pubkey] = state.index return state def new_transaction(self, from_account, to_account, amount): from_account, to_account = self.lookup_accounts(from_account, to_account) return OnchainTransaction(from_account.index, to_account.index, amount) def apply_transaction(self, stx): """ Records the state transition of the transaction being applied to the tree """ assert isinstance(stx, SignedTransaction) tx = stx.tx from_account, to_account = self.lookup_accounts(tx.from_idx, tx.to_idx) if from_account.balance < tx.amount: raise RuntimeError("Balance not sufficient to perform transfer") merkle_root = self._tree.root # Update `from` leaf, recording its state before modification state_from = deepcopy(from_account) from_account.nonce += 1 from_account.balance -= tx.amount proof_before_from = self._tree.proof(tx.from_idx) self._tree.update(tx.from_idx, from_account.hash()) # Update `to` leaf, recording its state before modification state_to = deepcopy(to_account) to_account.balance += tx.amount proof_before_to = self._tree.proof(tx.to_idx) self._tree.update(tx.to_idx, to_account.hash()) return TransactionProof(merkle_root, stx, state_from, state_to, proof_before_from, proof_before_to)
def test_make_proof(self): n_items = 2 << 28 tree = MerkleTree(n_items) for n in range(0, 2): tree.append(random_element()) exthash = random_element() nullifier = random_element() spend_preimage = random_element() spend_hash_IV = 0 spend_hash = LongsightL12p5_MP([spend_preimage, nullifier], spend_hash_IV) leaf_hash_IV = 0 leaf_hash = LongsightL12p5_MP([nullifier, spend_hash], leaf_hash_IV) leaf_idx = tree.append(leaf_hash) self.assertEqual(leaf_idx, tree.index(leaf_hash)) # Verify it exists in true leaf_proof = tree.proof(leaf_idx) self.assertTrue(leaf_proof.verify(tree.root)) # Generate proof wrapper = Miximus(NATIVE_LIB_PATH, VK_PATH, PK_PATH) tree_depth = wrapper.tree_depth snark_proof = wrapper.prove(tree.root, nullifier, spend_preimage, exthash, leaf_proof.address, leaf_proof.path) self.assertTrue(wrapper.verify(snark_proof))
def test_make_proof(self): wrapper = Mixer(NATIVE_LIB_PATH, VK_PATH, PK_PATH) tree_depth = wrapper.tree_depth n_items = 2 << (tree_depth - 1) tree = MerkleTree(n_items) for n in range(0, 2): tree.append(int(FQ.random())) wallet_address = int(FQ.random()) nullifier_secret = int(FQ.random()) nullifier_hash = mimc_hash([nullifier_secret, nullifier_secret]) leaf_hash = int( get_sha256_hash(to_hex(nullifier_secret), to_hex(wallet_address)), 16) leaf_idx = tree.append(leaf_hash) self.assertEqual(leaf_idx, tree.index(leaf_hash)) # Verify it exists in true leaf_proof = tree.proof(leaf_idx) self.assertTrue(leaf_proof.verify(tree.root)) # Generate proof snark_proof = wrapper.prove( tree.root, wallet_address, nullifier_hash, nullifier_secret, # (index)_2 bits reversed, i.e. [LSB, ... , MSB] leaf_proof.address, leaf_proof.path) self.assertTrue(wrapper.verify(snark_proof))
def test_make_proof(self): n_items = 2 << 28 tree = MerkleTree(n_items) for n in range(0, 2): tree.append(int(FQ.random())) exthash = int(FQ.random()) prehash = int(FQ.random()) secret = int(FQ.random()) msg = int(FQ.random()) leaf_hash = mimc_hash([secret]) sig_msg_hash = mimc_hash([msg]) leaf_idx = tree.append(leaf_hash) self.assertEqual(leaf_idx, tree.index(leaf_hash)) # Verify it exists in true leaf_proof = tree.proof(leaf_idx) self.assertTrue(leaf_proof.verify(tree.root)) self.assertTrue(prehash, sig_msg_hash) # Generate proof wrapper = Ssles(NATIVE_LIB_PATH, VK_PATH, PK_PATH) tree_depth = wrapper.tree_depth snark_proof = wrapper.prove(tree.root, secret, msg, exthash, prehash, leaf_proof.address, leaf_proof.path) self.assertTrue(wrapper.verify(snark_proof)) if __name__ == "__main__": unittest.main()
def test_make_proof(self): n_items = 2<<28 tree = MerkleTree(n_items) for n in range(0, 2): tree.append(int(FQ.random())) exthash = int(FQ.random()) secret = int(FQ.random()) leaf_hash = mimc_hash([secret]) leaf_idx = tree.append(leaf_hash) self.assertEqual(leaf_idx, tree.index(leaf_hash)) # Verify it exists in true leaf_proof = tree.proof(leaf_idx) self.assertTrue(leaf_proof.verify(tree.root)) # Generate proof wrapper = Miximus(NATIVE_LIB_PATH, VK_PATH, PK_PATH) tree_depth = wrapper.tree_depth snark_proof = wrapper.prove( tree.root, secret, exthash, leaf_proof.address, leaf_proof.path) self.assertTrue(wrapper.verify(snark_proof))
def test_known1(self): tree = MerkleTree(2) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual(tree.root, 3075442268020138823380831368198734873612490112867968717790651410945045657947) proof_a = tree.proof(0) self.assertEqual(proof_a.path, [item_b]) proof_b = tree.proof(1) self.assertEqual(proof_b.path, [item_a])
def test_known1(self): tree = MerkleTree(2) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual( tree.root, 13981856331482487152452149678096232821987624395720231314895268163963385035507 ) proof_a = tree.proof(0) self.assertEqual(proof_a.path, [item_b]) proof_b = tree.proof(1) self.assertEqual(proof_b.path, [item_a])
def test_known1(self): tree = MerkleTree(2) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual( tree.root, 12232803403448551110711645741717605608347940439638387632993385741901727947062 ) proof_a = tree.proof(0) self.assertEqual(proof_a.path, [item_b]) proof_b = tree.proof(1) self.assertEqual(proof_b.path, [item_a])
def test_known_2pow28(self): tree = MerkleTree(2 << 28) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual( tree.root, 10928083011190212400724282287039881565290562079447442292540304400330695864757 )
def test_incremental_sha256(self): n_items = 100 tree = MerkleTree(n_items, MerkleHasherSHA256) self.assertEqual(tree.root, None) self.assertEqual(len(tree), 0) previous_root = None for n in range(0, n_items): item = bytes([n]) * 32 tree.append(item) self.assertEqual(len(tree), n + 1) self.assertNotEqual(tree.root, previous_root) previous_root = tree.root proof = tree.proof(n) self.assertTrue(proof.verify(tree.root)) # Then verify all existing items can also be proven to be in the tree for m in range(0, len(tree) - 1): self.assertTrue(tree.proof(m).verify(tree.root))
def test_tree(self): n_items = 32 tree = MerkleTree(n_items) self.assertEqual(tree.root, None) self.assertEqual(len(tree), 0) previous_root = None hasher = hashlib.sha256() for n in range(0, n_items): hasher.update(bytes([n]) * 32) item = int.from_bytes(hasher.digest(), 'big') % SNARK_SCALAR_FIELD tree.append(item) self.assertEqual(len(tree), n + 1) self.assertNotEqual(tree.root, previous_root) previous_root = tree.root proof = tree.proof(n) self.assertTrue(proof.verify(tree.root)) # Then verify all existing items can also be proven to be in the tree for m in range(0, len(tree) - 1): self.assertTrue(tree.proof(m).verify(tree.root))
def test_incremental_longsight(self): n_items = 100 tree = MerkleTree(n_items, MerkleHasherLongsightF) self.assertEqual(tree.root, None) self.assertEqual(len(tree), 0) previous_root = None for n in range(0, n_items): hasher = hashlib.sha256() hasher.update(bytes([n]) * 32) item = int.from_bytes(hasher.digest(), 'little') % curve_order tree.append(item) self.assertEqual(len(tree), n + 1) self.assertNotEqual(tree.root, previous_root) previous_root = tree.root proof = tree.proof(n) self.assertTrue(proof.verify(tree.root)) # Then verify all existing items can also be proven to be in the tree for m in range(0, len(tree) - 1): self.assertTrue(tree.proof(m).verify(tree.root))
def test_known_2pow28(self): tree = MerkleTree(2 << 28) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual( tree.root, 12880293998234311228895747943713504338160238149993004139365982527556885579681 ) proof_a = tree.proof(0) self.assertTrue(proof_a.verify(tree.root)) proof_b = tree.proof(1) self.assertTrue(proof_b.verify(tree.root)) self.assertEqual( tree.leaf(0, 0), 3703141493535563179657531719960160174296085208671919316200479060314459804651 ) self.assertEqual( tree.leaf(1, 0), 13981856331482487152452149678096232821987624395720231314895268163963385035507 ) self.assertEqual( tree.leaf(2, 0), 4008582766686307301250960594183893449903725811265984514032955228389672705119 ) self.assertEqual( tree.leaf(1, 1), 17296471688945713021042054900108821045192859417413320566181654591511652308323 ) self.assertEqual( tree.leaf(2, 1), 4832852105446597958495745596582249246190817345027389430471458078394903639834 ) self.assertEqual( tree.leaf(13, 1), 14116139569958633576637617144876714429777518811711593939929091541932333542283 ) self.assertEqual( tree.leaf(22, 1), 16077039334695461958102978289003547153551663194787878097275872631374489043531 )
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)
def test_update(self): """ Verify that items in the tree can be updated """ tree = MerkleTree(2) tree.append(FQ.random()) tree.append(FQ.random()) proof_0_before = tree.proof(0) proof_1_before = tree.proof(1) root_before = tree.root self.assertTrue(proof_0_before.verify(tree.root)) self.assertTrue(proof_1_before.verify(tree.root)) leaf_0_after = FQ.random() tree.update(0, leaf_0_after) root_after_0 = tree.root proof_0_after = tree.proof(0) self.assertTrue(proof_0_after.verify(tree.root)) self.assertNotEqual(root_before, root_after_0) leaf_1_after = FQ.random() tree.update(1, leaf_1_after) root_after_1 = tree.root proof_1_after = tree.proof(1) self.assertTrue(proof_1_after.verify(tree.root)) self.assertNotEqual(root_before, root_after_1) self.assertNotEqual(root_after_0, root_after_1)
def test_known_2pow28(self): tree = MerkleTree(2<<28) item_a = 3703141493535563179657531719960160174296085208671919316200479060314459804651 tree.append(item_a) item_b = 134551314051432487569247388144051420116740427803855572138106146683954151557 tree.append(item_b) self.assertEqual(tree.root, 14972246236048249827985830600768475898195156734731557762844426864943654467818) proof_a = tree.proof(0) self.assertTrue(proof_a.verify(tree.root)) proof_b = tree.proof(1) self.assertTrue(proof_b.verify(tree.root)) self.assertEqual(tree.leaf(0, 0), 3703141493535563179657531719960160174296085208671919316200479060314459804651) self.assertEqual(tree.leaf(1, 0), 3075442268020138823380831368198734873612490112867968717790651410945045657947) self.assertEqual(tree.leaf(2, 0), 10399465128272526817755257959020023025563587559350936053132523411421423507430) self.assertEqual(tree.leaf(1, 1), 17296471688945713021042054900108821045192859417413320566181654591511652308323) self.assertEqual(tree.leaf(2, 1), 4832852105446597958495745596582249246190817345027389430471458078394903639834) self.assertEqual(tree.leaf(13, 1), 14116139569958633576637617144876714429777518811711593939929091541932333542283) self.assertEqual(tree.leaf(22, 1), 16077039334695461958102978289003547153551663194787878097275872631374489043531)
def __init__(self, tree_size): self._accounts = [] self._key2idx = dict() self._tree = MerkleTree(tree_size)