def orderFromJSON(jOrder, state): realmID = int(jOrder["realmID"]) orderID = int(jOrder["orderID"]) accountID = int(jOrder["accountID"]) walletAccountID = int(jOrder["walletAccountID"]) dualAuthPublicKeyX = int(jOrder["dualAuthPublicKeyX"]) dualAuthPublicKeyY = int(jOrder["dualAuthPublicKeyY"]) dualAuthSecretKey = int(jOrder["dualAuthSecretKey"]) tokenS = int(jOrder["tokenIdS"]) tokenB = int(jOrder["tokenIdB"]) tokenF = int(jOrder["tokenIdF"]) amountS = int(jOrder["amountS"]) amountB = int(jOrder["amountB"]) amountF = int(jOrder["amountF"]) allOrNone = int(jOrder["allOrNone"]) validSince = int(jOrder["validSince"]) validUntil = int(jOrder["validUntil"]) walletSplitPercentage = int(jOrder["walletSplitPercentage"]) waiveFeePercentage = int(jOrder["waiveFeePercentage"]) account = state.getAccount(accountID) walletAccount = state.getAccount(walletAccountID) order = Order(Point(account.publicKeyX, account.publicKeyY), Point(walletAccount.publicKeyX, walletAccount.publicKeyY), Point(dualAuthPublicKeyX, dualAuthPublicKeyY), dualAuthSecretKey, realmID, orderID, accountID, walletAccountID, tokenS, tokenB, tokenF, amountS, amountB, amountF, allOrNone, validSince, validUntil, walletSplitPercentage, waiveFeePercentage) order.sign(FQ(int(account.secretKey))) return order
def test_hash_scalars_known(self): self.assertEqual( pedersen_hash_scalars(b'test', 267), Point( FQ(6790798216812059804926342266703617627640027902964190490794793207272357201212 ), FQ(2522797517250455013248440571887865304858084343310097011302610004060289809689 ))) self.assertEqual( pedersen_hash_scalars( b'test', 6453482891510615431577168724743356132495662554103773572771861111634748265227 ), Point( FQ(6545697115159207040330446958704617656199928059562637738348733874272425400594 ), FQ(16414097465381367987194277536478439232201417933379523927469515207544654431390 ))) self.assertEqual( pedersen_hash_scalars( b'test', 21888242871839275222246405745257275088548364400416034343698204186575808495616 ), Point( FQ(16322787121012335146141962340685388833598805940095898416175167744309692564601 ), FQ(7671892447502767424995649701270280747270481283542925053047237428072257876309 )))
def orderFromJSON(jOrder, state): exchangeID = int(jOrder["exchangeID"]) orderID = int(jOrder["orderID"]) accountID = int(jOrder["accountID"]) dualAuthPublicKeyX = int(jOrder["dualAuthPublicKeyX"]) dualAuthPublicKeyY = int(jOrder["dualAuthPublicKeyY"]) dualAuthSecretKey = int(jOrder["dualAuthSecretKey"]) tokenS = int(jOrder["tokenIdS"]) tokenB = int(jOrder["tokenIdB"]) amountS = int(jOrder["amountS"]) amountB = int(jOrder["amountB"]) allOrNone = int(jOrder["allOrNone"]) validSince = int(jOrder["validSince"]) validUntil = int(jOrder["validUntil"]) buy = int(jOrder["buy"]) maxFeeBips = int(jOrder["maxFeeBips"]) feeBips = int(jOrder["feeBips"]) rebateBips = int(jOrder["rebateBips"]) account = state.getAccount(accountID) order = Order(Point(account.publicKeyX, account.publicKeyY), Point(dualAuthPublicKeyX, dualAuthPublicKeyY), dualAuthSecretKey, exchangeID, orderID, accountID, tokenS, tokenB, amountS, amountB, allOrNone, validSince, validUntil, buy, maxFeeBips, feeBips, rebateBips) order.signature = jOrder["signature"] return order
def test_6_recover_y(self): """ There are two y points for every x """ for _ in range(0, 10): p = self._point_r() q = Point.from_x(p.x) self.assertEqual(p.x, q.x) self.assertTrue(p.y in [q.y, -q.y]) # These confirm compatibility across implementations known_test_cases = [ (20616554786359396897066290204264220576319536076538991133935783866206841138898, 10592275084648178561464128859907688344447649297734555224341876545305639835999), (11610117029953798428826613242669939481045605849364609771767823351326159443609, 3722409228507723418678713896319610332389736117851027921973860155000856891140), (21680045038775759642189425577922609025982451102460978847266452551495203884482, 6168854640927408084732268325506202000962285527703379133980054444068219727690), (18879782252170350866370777185563748782908354718484814019474117245310535071541, 2946855428411022359321514310392164228862398839132752152798293872913224129374) ] for x, y in known_test_cases: x, y = FQ(x), FQ(y) q = Point.from_y(y) self.assertEqual(q.x, x)
def peak_update(prev_width, peaks: List[Point], item: Point) -> List[Point]: new_width = prev_width + 1 leaf_node = item * new_width cursor = leaf_node new_peaks = peaks new_peak = None for i in reversed(range(len(peaks))): # Starts from the right-most peak peak_height = len(peaks) - i prev_peak = peaks[i] # With the mountain map, check the peak exists or not correctly assert (prev_peak == Point.infinity()) is \ (True if MMR.peak_existence(prev_width, peak_height) else False) # Move cursor to the next peak. cursor = cursor * prev_peak.y # Update new peak if not MMR.peak_existence(new_width, peak_height): # Peak should be zero new_peaks[i] = Point.infinity() elif not MMR.peak_existence(prev_width, peak_height): assert new_peak is None, "There should be only one new peak" new_peaks[i] = cursor new_peak = cursor else: new_peaks[i] = prev_peak assert new_peak is not None, "Failed to find new peak" return new_peak
def test_mimc_eddsa(self): A = Point(FQ(1301009284721359989986872336829887838687570550075011148323334415657243668534), FQ(6027072831423449649615427623935115177649426117898838224822914942466592945166)) R = Point(FQ(16697780772074863636681870538986108875460311579901354831891912949591301444465), FQ(4226867824412371436973606126220323912943722787513450804471487686191426145939)) s = 740212824778436527565151771778503009743408793780835234261147965780852431216 m = [1, 2, 3] self.assertTrue(MiMCEdDSA.verify(A, (R,s), m))
def test_8_hash_to_point(self): p = Point.from_hash(b'test') expected = Point(x=14447835080060184026016688399206371580541195409649120233292541285797925116718, y=6491210871329023843020152497494661717176702609200142392074344830880218876421) self.assertEqual(p, expected) for _ in range(0, 10): entropy = urandom(10) p = Point.from_hash(entropy)
def test_8_hash_to_point(self): p = Point.from_hash(b'test') expected = Point(x=6310387441923805963163495340827050724868600896655464356695079365984952295953, y=12999349368805111542414555617351208271526681431102644160586079028197231734677) self.assertEqual(p, expected) for _ in range(0, 10): entropy = urandom(10) p = Point.from_hash(entropy)
def deserialize(cls, serialized): assert len(serialized) == 32 * 5 value = Field(int.from_bytes(serialized[0:32], 'little')) fee = Field(int.from_bytes(serialized[32:64], 'little')) sig_salt = Point.decompress(serialized[64:96]) excess = Point.decompress(serialized[96:128]) metadata = Field(int.from_bytes(serialized[128:160], 'little')) instance = cls(value, fee, sig_salt, excess, metadata) return instance
def test_hash_eddsa(self): # Used to verify compatibility with test_jubjub_eddsa.cpp A = Point(FQ(333671881179914989291633188949569309119725676183802886621140166987382124337), FQ(4050436616325076046600891135828313078248584449767955905006778857958871314574)) R = Point(FQ(21473010389772475573783051334263374448039981396476357164143587141689900886674), FQ(11330590229113935667895133446882512506792533479705847316689101265088791098646)) s = 21807294168737929637405719327036335125520717961882955117047593281820367379946 m = b'abc' self.assertTrue(EdDSA.verify(A, (R, s), m)) self.assertFalse(PureEdDSA.verify(A, (R, s), m))
def deserialize(cls, serialized): assert len(serialized) == 32 * 3 hh_outputs = Point.decompress(serialized[0:32]) hh_excess = Point.decompress(serialized[32:64]) signature = Signature( Field(int.from_bytes(serialized[96:128], 'little')), Point.decompress(serialized[64:96])) range_proof = json.loads(serialized[96:].decode('utf-8')) instance = cls(hh_outputs, hh_excess, signature, range_proof) return instance
def test_pure_eddsa(self): # Used to verify compatibility with test_jubjub_eddsa.cpp A = Point(FQ(333671881179914989291633188949569309119725676183802886621140166987382124337), FQ(4050436616325076046600891135828313078248584449767955905006778857958871314574)) R = Point(FQ(17815983127755465894346158776246779862712623073638768513395595796132990361464), FQ(947174453624106321442736396890323086851143728754269151257776508699019857364)) s = 13341814865473145800030207090487687417599620847405735706082771659861699337012 m = b'abcd' self.assertTrue(PureEdDSA.verify(A, (R, s), m)) self.assertFalse(EdDSA.verify(A, (R, s), m))
def test_hash_bytes_known(self): self.assertEqual( pedersen_hash_bytes(b'test', b"abc"), Point( FQ(9869277320722751484529016080276887338184240285836102740267608137843906399765 ), FQ(19790690237145851554496394080496962351633528315779989340140084430077208474328 ))) self.assertEqual( pedersen_hash_bytes(b'test', b"abcdefghijklmnopqrstuvwx"), Point( FQ(3966548799068703226441887746390766667253943354008248106643296790753369303077 ), FQ(12849086395963202120677663823933219043387904870880733726805962981354278512988 )))
def sign(value, k): k = FQ(k) B = Point.from_hash(b'eddsa_base') m = bytes.fromhex(hex(int(toBinaryString(value), 2))[2:]) R, S, A = eddsa_sign(m, k, B) assert eddsa_verify(A, R, S, m, B) return R, S
def deposit(self, accountID, secretKey, publicKeyX, publicKeyY, token, amount): # Copy the initial merkle root rootBefore = self._accountsTree._root if not (str(accountID) in self._accounts): accountBefore = copyAccountInfo(getDefaultAccount()) else: accountBefore = copyAccountInfo(self.getAccount(accountID)) proof = self._accountsTree.createProof(accountID) # Create the account if necessary if not (str(accountID) in self._accounts): self._accounts[str(accountID)] = Account( secretKey, Point(publicKeyX, publicKeyY)) account = self.getAccount(accountID) balanceUpdate = account.updateBalance(token, amount) # Update keys account.secretKey = str(secretKey) account.publicKeyX = str(publicKeyX) account.publicKeyY = str(publicKeyY) self._accountsTree.update(accountID, account.hash()) accountAfter = copyAccountInfo(account) rootAfter = self._accountsTree._root accountUpdate = AccountUpdateData(accountID, proof, rootBefore, rootAfter, accountBefore, accountAfter) return Deposit(amount, balanceUpdate, accountUpdate)
def width_from_peaks(peaks: List[Point]) -> int: width = 0 for i in range(len(peaks)): peak_height = len(peaks) - i if peaks[i] != Point.infinity(): width += 1 << (peak_height - 1) return width
def append(self, item: Point): new_width = self.width + 1 # Store leaf node # leaf_node = item * new_width leaf_node = item * new_width leaf_index = MMR.leaf_index(new_width) self.items[new_width] = item self.nodes[leaf_index] = leaf_node # When it is an odd leaf if new_width & 1: new_peaks = self.peaks new_peaks[len(new_peaks) - 1] = leaf_node # When it is an even leaf else: cursor = leaf_node cursor_index = leaf_index peak_node_index = MMR.peak_node_index(new_width) height = 1 while cursor_index != peak_node_index: height = height + 1 cursor_index = cursor_index + 1 # left_node_index = cursor_index - (1 << (height - 1)) left_node = self.nodes[left_node_index] cursor = cursor * left_node.y self.nodes[cursor_index] = cursor new_peaks = self.peaks[:-height] + [cursor] + [Point.infinity()] * (height - 1) self.peaks = new_peaks self.width = new_width
def test_signverify(self): B = Point.from_hash(b'eddsa_base') k = FQ.random(JUBJUB_L) A = B * k m = urandom(32) R, s = eddsa_sign(m, k, B, A) self.assertTrue(eddsa_verify(A, R, s, m, B))
def test_5_recover_x(self): """ There is one x point for every y """ for _ in range(0, 10): p = self._point_r() q = Point.from_y(p.y) self.assertEqual(p, q)
def test_5_recover_x(self): """ There is one x point for every y """ for _ in range(0, 10): p = self._point_r() q = Point.from_y(p.y) self.assertTrue(p.x in [q.x, -q.x])
def test_points(self): d = urandom(10) p = Point.from_hash(d) q = pedersen_hash_points(b'test', p) r = pedersen_hash_points(b'test', q) self.assertTrue(q.valid()) self.assertTrue(r.valid()) self.assertNotEqual(q, r)
def test_mont_double(self): """ Verified in Sage, using `ejubjub.py` Ensure that addition laws remain the same between Montgomery and Edwards coordinates """ q = Point.from_hash(b'x') mq = MontPoint(FQ(4828722366376575650251607168518886976429844446767098803596167689250506416759), FQ(12919092401030192644826086113396919334232812611316996694878363256143428656958)) self.assertEqual(q.as_mont(), mq) q2 = MontPoint(FQ(760569539648116659146730905587051427168718890872716379895718021693339839266), FQ(19523163946365579499783218718995636854804792079073783994015125253921919723342)) self.assertEqual(q.double().as_mont(), q2) for _ in range(0, 10): p = Point.from_hash(urandom(32)) self.assertEqual(p.as_mont().double().as_edwards_yz().as_point().as_edwards_yz(), p.double().as_edwards_yz())
def test_6_recover_y(self): """ There are two y points for every x """ for _ in range(0, 10): p = self._point_r() q = Point.from_x(p.x) self.assertEqual(p.x, q.x) self.assertTrue(p.y in [q.y, -q.y])
def test_hash_bits_known(self): self.assertEqual( pedersen_hash_bits( 'EdDSA_Verify.RAM', '101100110011111001100100101100010100011010100100001011101001000100100000001111101101111001001010111011101101011010010101101101101000000010000000101010110100011110101110111100111100011110110011100101011000000000110101111001110000101011011110100100011110010000110111010011000001000100101100101111001100100010110101100010001000000101111011011010010011110001110111101011110001111111100010010000110101000001010111000111011110111010010010000101110000011001111000101010001101100000110111111110011001110101011000110010111111000101001100010001011011101010101011101010110000111100101000000110011000011001101000001010110110010000110101011111100010111011100110111101110111011001001110100100110010100111001000001010101010010100010100101101000010100010000111110101111000101110' ), Point( FQ(16391910732431349989910402670442677728780476741314399751389577385062806845560 ), FQ(9557600014660247419117975756584483223203707451467643504980876223495155042156 )))
def test_signverify(self): B = Point.from_hash(b'eddsa_base') #B = None k, A = eddsa_random_keypair() m = urandom(32) smsg = eddsa_sign(m, k, B) self.assertTrue(eddsa_verify(*smsg, B)) smsg = pureeddsa_sign(m, k, B) self.assertTrue(pureeddsa_verify(*smsg, B))
def test_signverify(self): B = Point.from_hash(b'eddsa_base') k, A = EdDSA.random_keypair() m = urandom(32) # Hash-EdDSA smsg = EdDSA.sign(m, k, B) self.assertTrue(EdDSA.verify(*smsg, B)) # Pure-EdDSA (no message pre-hash) smsg = PureEdDSA.sign(m, k, B) self.assertTrue(PureEdDSA.verify(*smsg, B))
def test_hash_eddsa(self): # Used to verify compatibility with test_jubjub_eddsa.cpp B = Point( FQ(21609035313031231356478892405209584931807557563713540183143349090940105307553 ), FQ(845281570263603011277359323511710394920357596931617398831207691379369851278 )) A = Point( FQ(5616630816018221659484394091994939318481030030481519242876140465113436048304 ), FQ(8476221375891900895034976644661703008703725320613595264559419965669922411183 )) R = Point( FQ(17883110238616315155327756854433987355427639458557188556819876765548551765197 ), FQ(11833558192785987866925773659755699683735551950878443451361314529874236222818 )) s = 9920504625278683304895036460477595239370241328717115039061027107077120437288 m = b'abc' self.assertTrue(eddsa_verify(A, (R, s), m, B)) self.assertFalse(pureeddsa_verify(A, (R, s), m, B))
def test_pure_eddsa(self): # Used to verify compatibility with test_jubjub_eddsa.cpp B = Point( FQ(16117159321177103813813294286550615556837550473658220567209763364611339839115 ), FQ(11465736382824868633493204496205282307637286781164666440541087834417561817657 )) A = Point( FQ(7232078318593313024960606529959628262327760580530543297615441605656275483008 ), FQ(13445187542498117393920468884784587115570437154948817232436446927611108297778 )) R = Point( FQ(16748186150368319377210820880944935248945916993910817768852007732596413990860 ), FQ(4850962850934517657076914998696277193398065576910427229359881798401199408131 )) s = 9530517511211249528464523051059372760063486304291273287859289432498093931519 m = b'abcd' self.assertTrue(pureeddsa_verify(A, (R, s), m, B)) self.assertFalse(eddsa_verify(A, (R, s), m, B))
def peak_bagging(peaks: List[Point]) -> FQ: root_point = G width = PedersenMMR.width_from_peaks(peaks) for i in reversed(range(len(peaks))): # Starts from the right-most peak peak_height = len(peaks) - i peak = peaks[i] # With the mountain map, check the peak exists or not correctly assert (peak == Point.infinity()) is (False if MMR.peak_existence(width, peak_height) else True) # Update root point root_point = root_point * peak.y root_point = root_point * width return root_point.y
def test_3_validity(self): """ Verify that 10 random points can be converted to and from every other coordinate system without losing information or corruption. """ self.assertTrue(self._point_a().valid()) self.assertTrue(Point.infinity().valid()) self.assertTrue(EtecPoint.infinity().valid()) self.assertTrue(ProjPoint.infinity().valid()) for _ in range(0, 10): p = self._point_r() self._verify_via_all(p)