From 6fadd9d36595c894c13f5f452365da236724b6c7 Mon Sep 17 00:00:00 2001 From: kevincharm Date: Mon, 18 Mar 2024 22:46:35 +0800 Subject: [PATCH] Add BN254 (#55) * implement ethereum bn254 * pull in missing changes from geth * make G2 points affine in ValidatePairing * move bn254 to own dir * fix bn254 GT Base and Null * test G1 suite against gnark-crypto * adapt G2 test to gnark-crypto, fix bn254 marshal ids * fix G1 hashToPoint reference tests * fix pairing/bn254/gfp_amd64.s * use keccak256 instead of sha256 in bn254 * implement TestGT for bn254 * implement hashToField, expandMsgXmd * implement mapToPoint * implement hashToPoint * rename toPointG1 -> fromBigInt * add comments on mapToPoint, cleanup * fix TestPointG1_HashToPoint with new keccak256 impl * use ref implementation of expand_message_xmd * panic if DST length > 255 * remove unnecessary iteration in expandMsgXmd * update tests to use full length DSTs * set DST in group instead of suite * fix: actually write bytes in zeroPadBytes * fix: leftpad intermediate prb in expandMsgXmd * fix: leftpad intermediate xored hashes in expandMsgXmd * add instructions to create hash-to-point reference values, remove old TODO * remove irrelevant issue400 test for bn254 * use CX instead of R15 in amd64 replaying fix from geth, see: https://github.com/ethereum/go-ethereum/commit/ec64358ac999cb737277b92ee018f7bb782c724f When using -buildmode=shared, R15 is clobbered by a global variable access; use a different register instead. * remove gfp.h in bn254 * use geth's Unmarshal func: error out on invalid coordinates * make constants z0 and z1 private * check that random points are different in TestG1Ops * implement Stringer interface for bn254 groups * remove irrelevant benchmarks * implement SVDW from RFC9380 for bn254 G1 map-to-point * encode the right variable in hashToField * borrow expand_message_xmd implementation from kilic-bls12381 * update test vectors in TestPointG1_HashToPoint, TestHashToField * test expandMsgXmd against a copy of gnark's * fix default DST for hash-to-curve * remove unused fromBigInt func * add sources for gfp exp/sqrt functions * use curveB constant in g(x) * create new DST buffers instead of passing refs --- go.mod | 7 + go.sum | 21 +- pairing/bn254/LICENSE | 27 + pairing/bn254/README.md | 27 + pairing/bn254/adapter.go | 50 + pairing/bn254/adapter_test.go | 28 + pairing/bn254/bls_test.go | 14 + pairing/bn254/constants.go | 76 + pairing/bn254/curve.go | 258 ++ pairing/bn254/gfp.go | 142 + pairing/bn254/gfp12.go | 169 + pairing/bn254/gfp2.go | 165 + pairing/bn254/gfp6.go | 224 ++ pairing/bn254/gfp_amd64.s | 129 + pairing/bn254/gfp_arm64.s | 113 + pairing/bn254/gfp_decl.go | 25 + pairing/bn254/gfp_generic.go | 174 + pairing/bn254/group.go | 84 + pairing/bn254/lattice.go | 115 + pairing/bn254/mul_amd64.h | 181 ++ pairing/bn254/mul_arm64.h | 133 + pairing/bn254/mul_bmi2_amd64.h | 112 + pairing/bn254/optate.go | 270 ++ pairing/bn254/point.go | 723 +++++ pairing/bn254/point_test.go | 208 ++ pairing/bn254/suite.go | 218 ++ pairing/bn254/suite_test.go | 375 +++ pairing/bn254/test_vectors.go | 5517 ++++++++++++++++++++++++++++++++ pairing/bn254/twist.go | 217 ++ pairing/bn254/util.go | 13 + 30 files changed, 9814 insertions(+), 1 deletion(-) create mode 100644 pairing/bn254/LICENSE create mode 100644 pairing/bn254/README.md create mode 100644 pairing/bn254/adapter.go create mode 100644 pairing/bn254/adapter_test.go create mode 100644 pairing/bn254/bls_test.go create mode 100644 pairing/bn254/constants.go create mode 100644 pairing/bn254/curve.go create mode 100644 pairing/bn254/gfp.go create mode 100644 pairing/bn254/gfp12.go create mode 100644 pairing/bn254/gfp2.go create mode 100644 pairing/bn254/gfp6.go create mode 100644 pairing/bn254/gfp_amd64.s create mode 100644 pairing/bn254/gfp_arm64.s create mode 100644 pairing/bn254/gfp_decl.go create mode 100644 pairing/bn254/gfp_generic.go create mode 100644 pairing/bn254/group.go create mode 100644 pairing/bn254/lattice.go create mode 100644 pairing/bn254/mul_amd64.h create mode 100644 pairing/bn254/mul_arm64.h create mode 100644 pairing/bn254/mul_bmi2_amd64.h create mode 100644 pairing/bn254/optate.go create mode 100644 pairing/bn254/point.go create mode 100644 pairing/bn254/point_test.go create mode 100644 pairing/bn254/suite.go create mode 100644 pairing/bn254/suite_test.go create mode 100644 pairing/bn254/test_vectors.go create mode 100644 pairing/bn254/twist.go create mode 100644 pairing/bn254/util.go diff --git a/go.mod b/go.mod index 0972ae9e9..e755d185d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.18 require ( github.com/cloudflare/circl v1.3.7 + github.com/consensys/gnark-crypto v0.12.1 github.com/drand/kyber-bls12381 v0.3.1 github.com/jonboulle/clockwork v0.4.0 github.com/stretchr/testify v1.9.0 @@ -14,8 +15,14 @@ require ( ) require ( + github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index f46d2e94b..e02662443 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,33 @@ +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drand/kyber-bls12381 v0.3.1 h1:KWb8l/zYTP5yrvKTgvhOrk2eNPscbMiUOIeWBnmUxGo= github.com/drand/kyber-bls12381 v0.3.1/go.mod h1:H4y9bLPu7KZA/1efDg+jtJ7emKx+ro3PU7/jWUVt140= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -31,7 +48,9 @@ golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/pairing/bn254/LICENSE b/pairing/bn254/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/pairing/bn254/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pairing/bn254/README.md b/pairing/bn254/README.md new file mode 100644 index 000000000..b98c9e5d4 --- /dev/null +++ b/pairing/bn254/README.md @@ -0,0 +1,27 @@ +## bn254 + +Package bn254 implements a particular bilinear group. + +Note: this _is_ the curve implemented in Ethereum. + +Bilinear groups are the basis of many of the new cryptographic protocols that +have been proposed over the past decade. They consist of a triplet of groups +(G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ is a +generator of the respective group). That function is called a pairing function. + +This package specifically implements the Optimal Ate pairing over a 256-bit +Barreto-Naehrig curve as described in +http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible with +the implementation described in that paper. + +This package previously claimed to operate at a 128-bit security level. However, +recent improvements in attacks mean that is no longer true. See +https://moderncrypto.org/mail-archive/curves/2016/000740.html. + +## Kyber additions + +The basis for this package is [Cloudflare's bn256 implementation](https://github.com/cloudflare/bn256) +which itself is an improved version of the [official bn256 package](https://golang.org/x/crypto/bn256). +The package at hand maintains compatibility to Cloudflare's library. The biggest difference is the replacement of their +[public API](https://github.com/cloudflare/bn256/blob/master/bn256.go) by a new +one that is compatible to Kyber's scalar, point, group, and suite interfaces. diff --git a/pairing/bn254/adapter.go b/pairing/bn254/adapter.go new file mode 100644 index 000000000..c1c5b31fc --- /dev/null +++ b/pairing/bn254/adapter.go @@ -0,0 +1,50 @@ +package bn254 + +import ( + "github.com/drand/kyber" +) + +// SuiteBn254 is an adapter that implements the suites.Suite interface so that +// bn254 can be used as a common suite to generate key pairs for instance but +// still preserves the properties of the pairing (e.g. the Pair function). +// +// It's important to note that the Point function will generate a point +// compatible with public keys only (group G2) where the signature must be +// used as a point from the group G1. +type SuiteBn254 struct { + *Suite + kyber.Group +} + +// NewSuiteBn254 makes a new BN254 suite +func NewSuiteBn254() *SuiteBn254 { + return &SuiteBn254{ + Suite: NewSuite(), + } +} + +// Point generates a point from the G2 group that can only be used +// for public keys +func (s *SuiteBn254) Point() kyber.Point { + return s.G2().Point() +} + +// PointLen returns the length of a G2 point +func (s *SuiteBn254) PointLen() int { + return s.G2().PointLen() +} + +// Scalar generates a scalar +func (s *SuiteBn254) Scalar() kyber.Scalar { + return s.G1().Scalar() +} + +// ScalarLen returns the lenght of a scalar +func (s *SuiteBn254) ScalarLen() int { + return s.G1().ScalarLen() +} + +// String returns the name of the suite +func (s *SuiteBn254) String() string { + return "bn254.adapter" +} diff --git a/pairing/bn254/adapter_test.go b/pairing/bn254/adapter_test.go new file mode 100644 index 000000000..f5ae68f8f --- /dev/null +++ b/pairing/bn254/adapter_test.go @@ -0,0 +1,28 @@ +package bn254 + +import ( + "testing" + + "github.com/drand/kyber/util/key" + "github.com/stretchr/testify/require" +) + +func TestAdapter_SuiteBn254(t *testing.T) { + suite := NewSuiteBn254() + + pair := key.NewKeyPair(suite) + pubkey, err := pair.Public.MarshalBinary() + require.Nil(t, err) + privkey, err := pair.Private.MarshalBinary() + require.Nil(t, err) + + pubhex := suite.Point() + err = pubhex.UnmarshalBinary(pubkey) + require.Nil(t, err) + + privhex := suite.Scalar() + err = privhex.UnmarshalBinary(privkey) + require.Nil(t, err) + + require.Equal(t, "bn254.adapter", suite.String()) +} diff --git a/pairing/bn254/bls_test.go b/pairing/bn254/bls_test.go new file mode 100644 index 000000000..a47398fcf --- /dev/null +++ b/pairing/bn254/bls_test.go @@ -0,0 +1,14 @@ +package bn254 + +import ( + "testing" + + "github.com/drand/kyber/sign/bls" + "github.com/drand/kyber/sign/test" +) + +func TestBLSSchemeBN254G1(t *testing.T) { + suite := NewSuite() + s := bls.NewSchemeOnG1(suite) + test.SchemeTesting(t, s) +} diff --git a/pairing/bn254/constants.go b/pairing/bn254/constants.go new file mode 100644 index 000000000..53c5ed29f --- /dev/null +++ b/pairing/bn254/constants.go @@ -0,0 +1,76 @@ +package bn254 + +import ( + "math/big" +) + +func bigFromBase10(s string) *big.Int { + n, _ := new(big.Int).SetString(s, 10) + return n +} + +// u is the BN parameter. +var u = bigFromBase10("4965661367192848881") + +// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. +// Needs to be highly 2-adic for efficient SNARK key and proof generation. +// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081. +// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters. +var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") + +// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. +var p = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") + +// p2 is p, represented as little-endian 64-bit words. +var p2 = [4]uint64{0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} + +var curveB = newGFp(3) + +// np is the negative inverse of p, mod 2^256. +var np = [4]uint64{0x87d20782e4866389, 0x9ede7d651eca6ac9, 0xd8afcbd01833da80, 0xf57a22b791888c6b} + +// rN1 is R^-1 where R = 2^256 mod p. +var rN1 = &gfP{0xed84884a014afa37, 0xeb2022850278edf8, 0xcf63e9cfb74492d9, 0x2e67157159e5c639} + +// r2 is R^2 where R = 2^256 mod p. +var r2 = &gfP{0xf32cfc5b538afa89, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f} + +// r3 is R^3 where R = 2^256 mod p. +var r3 = &gfP{0xb1cd6dafda1530df, 0x62f210e6a7283db6, 0xef7f0b0c0ada0afb, 0x20fd6e902d592544} + +// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9. +var xiToPMinus1Over6 = &gfP2{gfP{0xa222ae234c492d72, 0xd00f02a4565de15b, 0xdc2ff3a253dfc926, 0x10a75716b3899551}, gfP{0xaf9ba69633144907, 0xca6b1d7387afb78a, 0x11bded5ef08a2087, 0x02f34d751a1f3a7c}} + +// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9. +var xiToPMinus1Over3 = &gfP2{gfP{0x6e849f1ea0aa4757, 0xaa1c7b6d89f89141, 0xb6e713cdfae0ca3a, 0x26694fbb4e82ebc3}, gfP{0xb5773b104563ab30, 0x347f91c8a9aa6454, 0x7a007127242e0991, 0x1956bcd8118214ec}} + +// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9. +var xiToPMinus1Over2 = &gfP2{gfP{0xa1d77ce45ffe77c7, 0x07affd117826d1db, 0x6d16bd27bb7edc6b, 0x2c87200285defecc}, gfP{0xe4bbdd0c2936b629, 0xbb30f162e133bacb, 0x31a9d1b6f9645366, 0x253570bea500f8dd}} + +// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9. +var xiToPSquaredMinus1Over3 = &gfP{0x3350c88e13e80b9c, 0x7dce557cdb5e56b9, 0x6001b4b8b615564a, 0x2682e617020217e0} + +// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p). +var xiTo2PSquaredMinus2Over3 = &gfP{0x71930c11d782e155, 0xa6bb947cffbe3323, 0xaa303344d4741444, 0x2c3b3f0d26594943} + +// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p). +var xiToPSquaredMinus1Over6 = &gfP{0xca8d800500fa1bf2, 0xf0c5d61468b39769, 0x0e201271ad0d4418, 0x04290f65bad856e6} + +// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9. +var xiTo2PMinus2Over3 = &gfP2{gfP{0x5dddfd154bd8c949, 0x62cb29a5a4445b60, 0x37bc870a0c7dd2b9, 0x24830a9d3171f0fd}, gfP{0x7361d77f843abe92, 0xa5bb2bd3273411fb, 0x9c941f314b3e2399, 0x15df9cddbb9fd3ec}} + +// g(Z) +var c1 = &gfP{0x115482203dbf392d, 0x926242126eaa626a, 0xe16a48076063c052, 0x07c5909386eddc93} + +// -Z / 2 +var c2 = &gfP{0xb461a4448976f7d5, 0xc6843fb439555fa7, 0x28f0d12384840918, 0x112ceb58a394e07d} + +// sqrt(-g(Z) * (3 * Z^2 + 4 * A)) +var c3 = &gfP{0x7c8487078735ab72, 0x51da7e0048bfb8d4, 0x945cfd183cbd7bf4, 0x0b70b1ec48ae62c6} + +// 4 * -g(Z) / (3 * Z^2 + 4 * A) +var c4 = &gfP{0xa79a2bdca0800831, 0x19fd7617e49815a1, 0xbb8d0c885550c7b1, 0x05c4aeb6ec7e0f48} + +var pMinus1Over2 = [4]uint64{0x9e10460b6c3e7ea3, 0xcbc0b548b438e546, 0xdc2822db40c0ac2e, 0x183227397098d014} + +var pPlus1Over4 = [4]uint64{0x4f082305b61f3f52, 0x65e05aa45a1c72a3, 0x6e14116da0605617, 0xc19139cb84c680a} diff --git a/pairing/bn254/curve.go b/pairing/bn254/curve.go new file mode 100644 index 000000000..3b2744d2d --- /dev/null +++ b/pairing/bn254/curve.go @@ -0,0 +1,258 @@ +package bn254 + +import ( + "fmt" + "math/big" +) + +// curvePoint implements the elliptic curve y²=x³+3. Points are kept in Jacobian +// form and t=z² when valid. G₁ is the set of points of this curve on GF(p). +type curvePoint struct { + x, y, z, t gfP +} + +// curveGen is the generator of G₁. +var curveGen = &curvePoint{ + x: *newGFp(1), + y: *newGFp(2), + z: *newGFp(1), + t: *newGFp(1), +} + +// evaluate the curve at x +func g(x *gfP) *gfP { + y := &gfP{} + gfpMul(y, x, x) + gfpMul(y, y, x) + gfpAdd(y, y, curveB) + return y +} + +func (c *curvePoint) String() string { + cpy := c.Clone() + cpy.MakeAffine() + x, y := &gfP{}, &gfP{} + montDecode(x, &cpy.x) + montDecode(y, &cpy.y) + return fmt.Sprintf("(%s, %s)", x.String(), y.String()) +} + +func (c *curvePoint) Set(a *curvePoint) { + c.x.Set(&a.x) + c.y.Set(&a.y) + c.z.Set(&a.z) + c.t.Set(&a.t) +} + +// IsOnCurve returns true iff c is on the curve. +func (c *curvePoint) IsOnCurve() bool { + c.MakeAffine() + if c.IsInfinity() { + return true + } + + y2, x3 := &gfP{}, &gfP{} + gfpMul(y2, &c.y, &c.y) + gfpMul(x3, &c.x, &c.x) + gfpMul(x3, x3, &c.x) + gfpAdd(x3, x3, curveB) + + return *y2 == *x3 +} + +func (c *curvePoint) SetInfinity() { + c.x = gfP{0} + c.y = *newGFp(1) + c.z = gfP{0} + c.t = gfP{0} +} + +func (c *curvePoint) IsInfinity() bool { + return c.z == gfP{0} +} + +func (c *curvePoint) Add(a, b *curvePoint) { + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + + // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] + // by [u1:s1:z1·z2] and [u2:s2:z1·z2] + // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ + z12, z22 := &gfP{}, &gfP{} + gfpMul(z12, &a.z, &a.z) + gfpMul(z22, &b.z, &b.z) + + u1, u2 := &gfP{}, &gfP{} + gfpMul(u1, &a.x, z22) + gfpMul(u2, &b.x, z12) + + t, s1 := &gfP{}, &gfP{} + gfpMul(t, &b.z, z22) + gfpMul(s1, &a.y, t) + + s2 := &gfP{} + gfpMul(t, &a.z, z12) + gfpMul(s2, &b.y, t) + + // Compute x = (2h)²(s²-u1-u2) + // where s = (s2-s1)/(u2-u1) is the slope of the line through + // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. + // This is also: + // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) + // = r² - j - 2v + // with the notations below. + h := &gfP{} + gfpSub(h, u2, u1) + xEqual := *h == gfP{0} + + gfpAdd(t, h, h) + // i = 4h² + i := &gfP{} + gfpMul(i, t, t) + // j = 4h³ + j := &gfP{} + gfpMul(j, h, i) + + gfpSub(t, s2, s1) + yEqual := *t == gfP{0} + if xEqual && yEqual { + c.Double(a) + return + } + r := &gfP{} + gfpAdd(r, t, t) + + v := &gfP{} + gfpMul(v, u1, i) + + // t4 = 4(s2-s1)² + t4, t6 := &gfP{}, &gfP{} + gfpMul(t4, r, r) + gfpAdd(t, v, v) + gfpSub(t6, t4, j) + + gfpSub(&c.x, t6, t) + + // Set y = -(2h)³(s1 + s*(x/4h²-u1)) + // This is also + // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j + gfpSub(t, v, &c.x) // t7 + gfpMul(t4, s1, j) // t8 + gfpAdd(t6, t4, t4) // t9 + gfpMul(t4, r, t) // t10 + gfpSub(&c.y, t4, t6) + + // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 + gfpAdd(t, &a.z, &b.z) // t11 + gfpMul(t4, t, t) // t12 + gfpSub(t, t4, z12) // t13 + gfpSub(t4, t, z22) // t14 + gfpMul(&c.z, t4, h) +} + +func (c *curvePoint) Double(a *curvePoint) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A, B, C := &gfP{}, &gfP{}, &gfP{} + gfpMul(A, &a.x, &a.x) + gfpMul(B, &a.y, &a.y) + gfpMul(C, B, B) + + t, t2 := &gfP{}, &gfP{} + gfpAdd(t, &a.x, B) + gfpMul(t2, t, t) + gfpSub(t, t2, A) + gfpSub(t2, t, C) + + d, e, f := &gfP{}, &gfP{}, &gfP{} + gfpAdd(d, t2, t2) + gfpAdd(t, A, A) + gfpAdd(e, t, A) + gfpMul(f, e, e) + + gfpAdd(t, d, d) + gfpSub(&c.x, f, t) + + gfpMul(&c.z, &a.y, &a.z) + gfpAdd(&c.z, &c.z, &c.z) + + gfpAdd(t, C, C) + gfpAdd(t2, t, t) + gfpAdd(t, t2, t2) + gfpSub(&c.y, d, &c.x) + gfpMul(t2, e, &c.y) + gfpSub(&c.y, t2, t) +} + +func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) { + precomp := [1 << 2]*curvePoint{nil, {}, {}, {}} + precomp[1].Set(a) + precomp[2].Set(a) + gfpMul(&precomp[2].x, &precomp[2].x, xiTo2PSquaredMinus2Over3) + precomp[3].Add(precomp[1], precomp[2]) + + multiScalar := curveLattice.Multi(scalar) + + sum := &curvePoint{} + sum.SetInfinity() + t := &curvePoint{} + + for i := len(multiScalar) - 1; i >= 0; i-- { + t.Double(sum) + if multiScalar[i] == 0 { + sum.Set(t) + } else { + sum.Add(t, precomp[multiScalar[i]]) + } + } + c.Set(sum) +} + +func (c *curvePoint) MakeAffine() { + if c.z == *newGFp(1) { + return + } else if c.z == *newGFp(0) { + c.x = gfP{0} + c.y = *newGFp(1) + c.t = gfP{0} + return + } + + zInv := &gfP{} + zInv.Invert(&c.z) + + t, zInv2 := &gfP{}, &gfP{} + gfpMul(t, &c.y, zInv) + gfpMul(zInv2, zInv, zInv) + + gfpMul(&c.x, &c.x, zInv2) + gfpMul(&c.y, t, zInv2) + + c.z = *newGFp(1) + c.t = *newGFp(1) +} + +func (c *curvePoint) Neg(a *curvePoint) { + c.x.Set(&a.x) + gfpNeg(&c.y, &a.y) + c.z.Set(&a.z) + c.t = gfP{0} +} + +// Clone makes a hard copy of the curve point +func (c *curvePoint) Clone() *curvePoint { + n := &curvePoint{} + copy(n.x[:], c.x[:]) + copy(n.y[:], c.y[:]) + copy(n.z[:], c.z[:]) + copy(n.t[:], c.t[:]) + + return n +} diff --git a/pairing/bn254/gfp.go b/pairing/bn254/gfp.go new file mode 100644 index 000000000..ba95a6621 --- /dev/null +++ b/pairing/bn254/gfp.go @@ -0,0 +1,142 @@ +package bn254 + +import ( + "errors" + "fmt" + "math/big" +) + +type gfP [4]uint64 + +func newGFp(x int64) (out *gfP) { + if x >= 0 { + out = &gfP{uint64(x)} + } else { + out = &gfP{uint64(-x)} + gfpNeg(out, out) + } + + montEncode(out, out) + return out +} + +func newGFpFromBase10(x string) *gfP { + bx, _ := new(big.Int).SetString(x, 10) + bx = bx.Mod(bx, p) + out := &gfP{} + out.Unmarshal(zeroPadBytes(bx.Bytes(), 32)) + montEncode(out, out) + return out +} + +func (e *gfP) String() string { + c := &gfP{} + c.Set(e) + montDecode(c, c) + return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", c[3], c[2], c[1], c[0]) +} + +func (e *gfP) Set(f *gfP) { + e[0] = f[0] + e[1] = f[1] + e[2] = f[2] + e[3] = f[3] +} + +func (e *gfP) Invert(f *gfP) { + bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} + + sum, power := &gfP{}, &gfP{} + sum.Set(rN1) + power.Set(f) + + for word := 0; word < 4; word++ { + for bit := uint(0); bit < 64; bit++ { + if (bits[word]>>bit)&1 == 1 { + gfpMul(sum, sum, power) + } + gfpMul(power, power, power) + } + } + + gfpMul(sum, sum, r3) + e.Set(sum) +} + +// Borrowed from: https://github.com/cloudflare/bn256/blob/master/gfp.go#L63 +func (e *gfP) Exp(f *gfP, bits [4]uint64) { + sum, power := &gfP{}, &gfP{} + sum.Set(rN1) + power.Set(f) + + for word := 0; word < 4; word++ { + for bit := uint(0); bit < 64; bit++ { + if (bits[word]>>bit)&1 == 1 { + gfpMul(sum, sum, power) + } + gfpMul(power, power, power) + } + } + + gfpMul(sum, sum, r3) + e.Set(sum) +} + +// Borrowed from: https://github.com/cloudflare/bn256/blob/master/gfp.go#L85 +func (e *gfP) Sqrt(f *gfP) { + // Since p = 4k+3, then e = f^(k+1) is a root of f. + e.Exp(f, pPlus1Over4) +} + +func (e *gfP) Marshal(out []byte) { + for w := uint(0); w < 4; w++ { + for b := uint(0); b < 8; b++ { + out[8*w+b] = byte(e[3-w] >> (56 - 8*b)) + } + } +} + +func (e *gfP) Unmarshal(in []byte) error { + // Unmarshal the bytes into little endian form + for w := uint(0); w < 4; w++ { + e[3-w] = 0 + for b := uint(0); b < 8; b++ { + e[3-w] += uint64(in[8*w+b]) << (56 - 8*b) + } + } + // Ensure the point respects the curve modulus + for i := 3; i >= 0; i-- { + if e[i] < p2[i] { + return nil + } + if e[i] > p2[i] { + return errors.New("bn254: coordinate exceeds modulus") + } + } + return errors.New("bn254: coordinate equals modulus") +} + +func montEncode(c, a *gfP) { gfpMul(c, a, r2) } +func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) } + +// https://datatracker.ietf.org/doc/html/rfc9380/#name-the-sgn0-function +func sgn0(e *gfP) int { + x := &gfP{} + montDecode(x, e) + return int(x[0] & 1) +} + +// Borrowed from: https://github.com/cloudflare/bn256/blob/master/gfp.go#L123 +func legendre(e *gfP) int { + f := &gfP{} + // Since p = 4k+3, then e^(2k+1) is the Legendre symbol of e. + f.Exp(e, pMinus1Over2) + + montDecode(f, f) + + if *f != [4]uint64{} { + return 2*int(f[0]&1) - 1 + } + + return 0 +} diff --git a/pairing/bn254/gfp12.go b/pairing/bn254/gfp12.go new file mode 100644 index 000000000..292775ebc --- /dev/null +++ b/pairing/bn254/gfp12.go @@ -0,0 +1,169 @@ +package bn254 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +import ( + "math/big" +) + +// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 +// where ω²=τ. +type gfP12 struct { + x, y gfP6 // value is xω + y +} + +func (e *gfP12) String() string { + return "(" + e.x.String() + "," + e.y.String() + ")" +} + +func (e *gfP12) Set(a *gfP12) *gfP12 { + e.x.Set(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP12) SetZero() *gfP12 { + e.x.SetZero() + e.y.SetZero() + return e +} + +func (e *gfP12) SetOne() *gfP12 { + e.x.SetZero() + e.y.SetOne() + return e +} + +func (e *gfP12) IsZero() bool { + return e.x.IsZero() && e.y.IsZero() +} + +func (e *gfP12) IsOne() bool { + return e.x.IsZero() && e.y.IsOne() +} + +func (e *gfP12) Conjugate(a *gfP12) *gfP12 { + e.x.Neg(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP12) Neg(a *gfP12) *gfP12 { + e.x.Neg(&a.x) + e.y.Neg(&a.y) + return e +} + +// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p +func (e *gfP12) Frobenius(a *gfP12) *gfP12 { + e.x.Frobenius(&a.x) + e.y.Frobenius(&a.y) + e.x.MulScalar(&e.x, xiToPMinus1Over6) + return e +} + +// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² +func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { + e.x.FrobeniusP2(&a.x) + e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6) + e.y.FrobeniusP2(&a.y) + return e +} + +func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 { + e.x.FrobeniusP4(&a.x) + e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3) + e.y.FrobeniusP4(&a.y) + return e +} + +func (e *gfP12) Add(a, b *gfP12) *gfP12 { + e.x.Add(&a.x, &b.x) + e.y.Add(&a.y, &b.y) + return e +} + +func (e *gfP12) Sub(a, b *gfP12) *gfP12 { + e.x.Sub(&a.x, &b.x) + e.y.Sub(&a.y, &b.y) + return e +} + +func (e *gfP12) Mul(a, b *gfP12) *gfP12 { + tx := (&gfP6{}).Mul(&a.x, &b.y) + t := (&gfP6{}).Mul(&b.x, &a.y) + tx.Add(tx, t) + + ty := (&gfP6{}).Mul(&a.y, &b.y) + t.Mul(&a.x, &b.x).MulTau(t) + + e.x.Set(tx) + e.y.Add(ty, t) + return e +} + +func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 { + e.x.Mul(&e.x, b) + e.y.Mul(&e.y, b) + return e +} + +func (e *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 { + sum := (&gfP12{}).SetOne() + t := &gfP12{} + + for i := power.BitLen() - 1; i >= 0; i-- { + t.Square(sum) + if power.Bit(i) != 0 { + sum.Mul(t, a) + } else { + sum.Set(t) + } + } + + e.Set(sum) + return e +} + +func (e *gfP12) Square(a *gfP12) *gfP12 { + // Complex squaring algorithm + v0 := (&gfP6{}).Mul(&a.x, &a.y) + + t := (&gfP6{}).MulTau(&a.x) + t.Add(&a.y, t) + ty := (&gfP6{}).Add(&a.x, &a.y) + ty.Mul(ty, t).Sub(ty, v0) + t.MulTau(v0) + ty.Sub(ty, t) + + e.x.Add(v0, v0) + e.y.Set(ty) + return e +} + +func (e *gfP12) Invert(a *gfP12) *gfP12 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t1, t2 := &gfP6{}, &gfP6{} + + t1.Square(&a.x) + t2.Square(&a.y) + t1.MulTau(t1).Sub(t2, t1) + t2.Invert(t1) + + e.x.Neg(&a.x) + e.y.Set(&a.y) + e.MulScalar(e, t2) + return e +} + +// Clone makes a hard copy of the field +func (e *gfP12) Clone() *gfP12 { + n := &gfP12{} + n.x = e.x.Clone() + n.y = e.y.Clone() + + return n +} diff --git a/pairing/bn254/gfp2.go b/pairing/bn254/gfp2.go new file mode 100644 index 000000000..eb842ad1a --- /dev/null +++ b/pairing/bn254/gfp2.go @@ -0,0 +1,165 @@ +package bn254 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +// gfP2 implements a field of size p² as a quadratic extension of the base field +// where i²=-1. +type gfP2 struct { + x, y gfP // value is xi+y. +} + +func gfP2Decode(in *gfP2) *gfP2 { + out := &gfP2{} + montDecode(&out.x, &in.x) + montDecode(&out.y, &in.y) + return out +} + +func (e *gfP2) String() string { + return "(" + e.x.String() + ", " + e.y.String() + ")" +} + +func (e *gfP2) Set(a *gfP2) *gfP2 { + e.x.Set(&a.x) + e.y.Set(&a.y) + return e +} + +func (e *gfP2) SetZero() *gfP2 { + e.x = gfP{0} + e.y = gfP{0} + return e +} + +func (e *gfP2) SetOne() *gfP2 { + e.x = gfP{0} + e.y = *newGFp(1) + return e +} + +func (e *gfP2) IsZero() bool { + zero := gfP{0} + return e.x == zero && e.y == zero +} + +func (e *gfP2) IsOne() bool { + zero, one := gfP{0}, *newGFp(1) + return e.x == zero && e.y == one +} + +func (e *gfP2) Conjugate(a *gfP2) *gfP2 { + e.y.Set(&a.y) + gfpNeg(&e.x, &a.x) + return e +} + +func (e *gfP2) Neg(a *gfP2) *gfP2 { + gfpNeg(&e.x, &a.x) + gfpNeg(&e.y, &a.y) + return e +} + +func (e *gfP2) Add(a, b *gfP2) *gfP2 { + gfpAdd(&e.x, &a.x, &b.x) + gfpAdd(&e.y, &a.y, &b.y) + return e +} + +func (e *gfP2) Sub(a, b *gfP2) *gfP2 { + gfpSub(&e.x, &a.x, &b.x) + gfpSub(&e.y, &a.y, &b.y) + return e +} + +// See "Multiplication and Squaring in Pairing-Friendly Fields", +// http://eprint.iacr.org/2006/471.pdf +func (e *gfP2) Mul(a, b *gfP2) *gfP2 { + tx, t := &gfP{}, &gfP{} + gfpMul(tx, &a.x, &b.y) + gfpMul(t, &b.x, &a.y) + gfpAdd(tx, tx, t) + + ty := &gfP{} + gfpMul(ty, &a.y, &b.y) + gfpMul(t, &a.x, &b.x) + gfpSub(ty, ty, t) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 { + gfpMul(&e.x, &a.x, b) + gfpMul(&e.y, &a.y, b) + return e +} + +// MulXi sets e=ξa where ξ=i+9 and then returns e. +func (e *gfP2) MulXi(a *gfP2) *gfP2 { + // (xi+y)(i+9) = (9x+y)i+(9y-x) + tx := &gfP{} + gfpAdd(tx, &a.x, &a.x) + gfpAdd(tx, tx, tx) + gfpAdd(tx, tx, tx) + gfpAdd(tx, tx, &a.x) + + gfpAdd(tx, tx, &a.y) + + ty := &gfP{} + gfpAdd(ty, &a.y, &a.y) + gfpAdd(ty, ty, ty) + gfpAdd(ty, ty, ty) + gfpAdd(ty, ty, &a.y) + + gfpSub(ty, ty, &a.x) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) Square(a *gfP2) *gfP2 { + // Complex squaring algorithm: + // (xi+y)² = (x+y)(y-x) + 2*i*x*y + tx, ty := &gfP{}, &gfP{} + gfpSub(tx, &a.y, &a.x) + gfpAdd(ty, &a.x, &a.y) + gfpMul(ty, tx, ty) + + gfpMul(tx, &a.x, &a.y) + gfpAdd(tx, tx, tx) + + e.x.Set(tx) + e.y.Set(ty) + return e +} + +func (e *gfP2) Invert(a *gfP2) *gfP2 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + t1, t2 := &gfP{}, &gfP{} + gfpMul(t1, &a.x, &a.x) + gfpMul(t2, &a.y, &a.y) + gfpAdd(t1, t1, t2) + + inv := &gfP{} + inv.Invert(t1) + + gfpNeg(t1, &a.x) + + gfpMul(&e.x, t1, inv) + gfpMul(&e.y, &a.y, inv) + return e +} + +// Clone makes a hard copy of the field +func (e *gfP2) Clone() gfP2 { + n := gfP2{} + copy(n.x[:], e.x[:]) + copy(n.y[:], e.y[:]) + + return n +} diff --git a/pairing/bn254/gfp6.go b/pairing/bn254/gfp6.go new file mode 100644 index 000000000..758c086b9 --- /dev/null +++ b/pairing/bn254/gfp6.go @@ -0,0 +1,224 @@ +package bn254 + +// For details of the algorithms used, see "Multiplication and Squaring on +// Pairing-Friendly Fields, Devegili et al. +// http://eprint.iacr.org/2006/471.pdf. + +// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ +// and ξ=i+9. +type gfP6 struct { + x, y, z gfP2 // value is xτ² + yτ + z +} + +func (e *gfP6) String() string { + return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" +} + +func (e *gfP6) Set(a *gfP6) *gfP6 { + e.x.Set(&a.x) + e.y.Set(&a.y) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) SetZero() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetZero() + return e +} + +func (e *gfP6) SetOne() *gfP6 { + e.x.SetZero() + e.y.SetZero() + e.z.SetOne() + return e +} + +func (e *gfP6) IsZero() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() +} + +func (e *gfP6) IsOne() bool { + return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() +} + +func (e *gfP6) Neg(a *gfP6) *gfP6 { + e.x.Neg(&a.x) + e.y.Neg(&a.y) + e.z.Neg(&a.z) + return e +} + +func (e *gfP6) Frobenius(a *gfP6) *gfP6 { + e.x.Conjugate(&a.x) + e.y.Conjugate(&a.y) + e.z.Conjugate(&a.z) + + e.x.Mul(&e.x, xiTo2PMinus2Over3) + e.y.Mul(&e.y, xiToPMinus1Over3) + return e +} + +// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z +func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { + // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) + e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3) + // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) + e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { + e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) + e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3) + e.z.Set(&a.z) + return e +} + +func (e *gfP6) Add(a, b *gfP6) *gfP6 { + e.x.Add(&a.x, &b.x) + e.y.Add(&a.y, &b.y) + e.z.Add(&a.z, &b.z) + return e +} + +func (e *gfP6) Sub(a, b *gfP6) *gfP6 { + e.x.Sub(&a.x, &b.x) + e.y.Sub(&a.y, &b.y) + e.z.Sub(&a.z, &b.z) + return e +} + +func (e *gfP6) Mul(a, b *gfP6) *gfP6 { + // "Multiplication and Squaring on Pairing-Friendly Fields" + // Section 4, Karatsuba method. + // http://eprint.iacr.org/2006/471.pdf + v0 := (&gfP2{}).Mul(&a.z, &b.z) + v1 := (&gfP2{}).Mul(&a.y, &b.y) + v2 := (&gfP2{}).Mul(&a.x, &b.x) + + t0 := (&gfP2{}).Add(&a.x, &a.y) + t1 := (&gfP2{}).Add(&b.x, &b.y) + tz := (&gfP2{}).Mul(t0, t1) + tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0) + + t0.Add(&a.y, &a.z) + t1.Add(&b.y, &b.z) + ty := (&gfP2{}).Mul(t0, t1) + t0.MulXi(v2) + ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0) + + t0.Add(&a.x, &a.z) + t1.Add(&b.x, &b.z) + tx := (&gfP2{}).Mul(t0, t1) + tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2) + + e.x.Set(tx) + e.y.Set(ty) + e.z.Set(tz) + return e +} + +func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { + e.x.Mul(&a.x, b) + e.y.Mul(&a.y, b) + e.z.Mul(&a.z, b) + return e +} + +func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 { + e.x.MulScalar(&a.x, b) + e.y.MulScalar(&a.y, b) + e.z.MulScalar(&a.z, b) + return e +} + +// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ +func (e *gfP6) MulTau(a *gfP6) *gfP6 { + tz := (&gfP2{}).MulXi(&a.x) + ty := (&gfP2{}).Set(&a.y) + + e.y.Set(&a.z) + e.x.Set(ty) + e.z.Set(tz) + return e +} + +func (e *gfP6) Square(a *gfP6) *gfP6 { + v0 := (&gfP2{}).Square(&a.z) + v1 := (&gfP2{}).Square(&a.y) + v2 := (&gfP2{}).Square(&a.x) + + c0 := (&gfP2{}).Add(&a.x, &a.y) + c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0) + + c1 := (&gfP2{}).Add(&a.y, &a.z) + c1.Square(c1).Sub(c1, v0).Sub(c1, v1) + xiV2 := (&gfP2{}).MulXi(v2) + c1.Add(c1, xiV2) + + c2 := (&gfP2{}).Add(&a.x, &a.z) + c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2) + + e.x.Set(c2) + e.y.Set(c1) + e.z.Set(c0) + return e +} + +func (e *gfP6) Invert(a *gfP6) *gfP6 { + // See "Implementing cryptographic pairings", M. Scott, section 3.2. + // ftp://136.206.11.249/pub/crypto/pairings.pdf + + // Here we can give a short explanation of how it works: let j be a cubic root of + // unity in GF(p²) so that 1+j+j²=0. + // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = (xτ² + yτ + z)(Cτ²+Bτ+A) + // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). + // + // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) + // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) + // + // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) + t1 := (&gfP2{}).Mul(&a.x, &a.y) + t1.MulXi(t1) + + A := (&gfP2{}).Square(&a.z) + A.Sub(A, t1) + + B := (&gfP2{}).Square(&a.x) + B.MulXi(B) + t1.Mul(&a.y, &a.z) + B.Sub(B, t1) + + C := (&gfP2{}).Square(&a.y) + t1.Mul(&a.x, &a.z) + C.Sub(C, t1) + + F := (&gfP2{}).Mul(C, &a.y) + F.MulXi(F) + t1.Mul(A, &a.z) + F.Add(F, t1) + t1.Mul(B, &a.x).MulXi(t1) + F.Add(F, t1) + + F.Invert(F) + + e.x.Mul(C, F) + e.y.Mul(B, F) + e.z.Mul(A, F) + return e +} + +// Clone makes a hard copy of the field +func (e *gfP6) Clone() gfP6 { + n := gfP6{ + x: e.x.Clone(), + y: e.y.Clone(), + z: e.z.Clone(), + } + + return n +} diff --git a/pairing/bn254/gfp_amd64.s b/pairing/bn254/gfp_amd64.s new file mode 100644 index 000000000..64c97eaed --- /dev/null +++ b/pairing/bn254/gfp_amd64.s @@ -0,0 +1,129 @@ +// +build amd64,!generic + +#define storeBlock(a0,a1,a2,a3, r) \ + MOVQ a0, 0+r \ + MOVQ a1, 8+r \ + MOVQ a2, 16+r \ + MOVQ a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVQ 0+r, a0 \ + MOVQ 8+r, a1 \ + MOVQ 16+r, a2 \ + MOVQ 24+r, a3 + +#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \ + \ // b = a-p + MOVQ a0, b0 \ + MOVQ a1, b1 \ + MOVQ a2, b2 \ + MOVQ a3, b3 \ + MOVQ a4, b4 \ + \ + SUBQ ·p2+0(SB), b0 \ + SBBQ ·p2+8(SB), b1 \ + SBBQ ·p2+16(SB), b2 \ + SBBQ ·p2+24(SB), b3 \ + SBBQ $0, b4 \ + \ + \ // if b is negative then return a + \ // else return b + CMOVQCC b0, a0 \ + CMOVQCC b1, a1 \ + CMOVQCC b2, a2 \ + CMOVQCC b3, a3 + +#include "mul_amd64.h" +#include "mul_bmi2_amd64.h" + +TEXT ·gfpNeg(SB),0,$0-16 + MOVQ ·p2+0(SB), R8 + MOVQ ·p2+8(SB), R9 + MOVQ ·p2+16(SB), R10 + MOVQ ·p2+24(SB), R11 + + MOVQ a+8(FP), DI + SUBQ 0(DI), R8 + SBBQ 8(DI), R9 + SBBQ 16(DI), R10 + SBBQ 24(DI), R11 + + MOVQ $0, AX + gfpCarry(R8,R9,R10,R11,AX, R12,R13,R14,CX,BX) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpAdd(SB),0,$0-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + loadBlock(0(DI), R8,R9,R10,R11) + MOVQ $0, R12 + + ADDQ 0(SI), R8 + ADCQ 8(SI), R9 + ADCQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0, R12 + + gfpCarry(R8,R9,R10,R11,R12, R13,R14,CX,AX,BX) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpSub(SB),0,$0-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + loadBlock(0(DI), R8,R9,R10,R11) + + MOVQ ·p2+0(SB), R12 + MOVQ ·p2+8(SB), R13 + MOVQ ·p2+16(SB), R14 + MOVQ ·p2+24(SB), CX + MOVQ $0, AX + + SUBQ 0(SI), R8 + SBBQ 8(SI), R9 + SBBQ 16(SI), R10 + SBBQ 24(SI), R11 + + CMOVQCC AX, R12 + CMOVQCC AX, R13 + CMOVQCC AX, R14 + CMOVQCC AX, CX + + ADDQ R12, R8 + ADCQ R13, R9 + ADCQ R14, R10 + ADCQ CX, R11 + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11, 0(DI)) + RET + +TEXT ·gfpMul(SB),0,$160-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + // Jump to a slightly different implementation if MULX isn't supported. + CMPB ·hasBMI2(SB), $0 + JE nobmi2Mul + + mulBMI2(0(DI),8(DI),16(DI),24(DI), 0(SI)) + storeBlock( R8, R9,R10,R11, 0(SP)) + storeBlock(R12,R13,R14,CX, 32(SP)) + gfpReduceBMI2() + JMP end + +nobmi2Mul: + mul(0(DI),8(DI),16(DI),24(DI), 0(SI), 0(SP)) + gfpReduce(0(SP)) + +end: + MOVQ c+0(FP), DI + storeBlock(R12,R13,R14,CX, 0(DI)) + RET diff --git a/pairing/bn254/gfp_arm64.s b/pairing/bn254/gfp_arm64.s new file mode 100644 index 000000000..c65e80168 --- /dev/null +++ b/pairing/bn254/gfp_arm64.s @@ -0,0 +1,113 @@ +// +build arm64,!generic + +#define storeBlock(a0,a1,a2,a3, r) \ + MOVD a0, 0+r \ + MOVD a1, 8+r \ + MOVD a2, 16+r \ + MOVD a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVD 0+r, a0 \ + MOVD 8+r, a1 \ + MOVD 16+r, a2 \ + MOVD 24+r, a3 + +#define loadModulus(p0,p1,p2,p3) \ + MOVD ·p2+0(SB), p0 \ + MOVD ·p2+8(SB), p1 \ + MOVD ·p2+16(SB), p2 \ + MOVD ·p2+24(SB), p3 + +#include "mul_arm64.h" + +TEXT ·gfpNeg(SB),0,$0-16 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + loadModulus(R5,R6,R7,R8) + + SUBS R1, R5, R1 + SBCS R2, R6, R2 + SBCS R3, R7, R3 + SBCS R4, R8, R4 + + SUBS R5, R1, R5 + SBCS R6, R2, R6 + SBCS R7, R3, R7 + SBCS R8, R4, R8 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpAdd(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + MOVD ZR, R0 + + ADDS R5, R1 + ADCS R6, R2 + ADCS R7, R3 + ADCS R8, R4 + ADCS ZR, R0 + + SUBS R9, R1, R5 + SBCS R10, R2, R6 + SBCS R11, R3, R7 + SBCS R12, R4, R8 + SBCS ZR, R0, R0 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpSub(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + + SUBS R5, R1 + SBCS R6, R2 + SBCS R7, R3 + SBCS R8, R4 + + CSEL CS, ZR, R9, R9 + CSEL CS, ZR, R10, R10 + CSEL CS, ZR, R11, R11 + CSEL CS, ZR, R12, R12 + + ADDS R9, R1 + ADCS R10, R2 + ADCS R11, R3 + ADCS R12, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpMul(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + + mul(R9,R10,R11,R12,R13,R14,R15,R16) + gfpReduce() + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET diff --git a/pairing/bn254/gfp_decl.go b/pairing/bn254/gfp_decl.go new file mode 100644 index 000000000..8c5429c52 --- /dev/null +++ b/pairing/bn254/gfp_decl.go @@ -0,0 +1,25 @@ +//go:build (amd64 && !generic) || (arm64 && !generic) +// +build amd64,!generic arm64,!generic + +package bn254 + +// This file contains forward declarations for the architecture-specific +// assembly implementations of these functions, provided that they exist. + +import ( + "golang.org/x/sys/cpu" +) + +var hasBMI2 = cpu.X86.HasBMI2 + +// go:noescape +func gfpNeg(c, a *gfP) + +//go:noescape +func gfpAdd(c, a, b *gfP) + +//go:noescape +func gfpSub(c, a, b *gfP) + +//go:noescape +func gfpMul(c, a, b *gfP) diff --git a/pairing/bn254/gfp_generic.go b/pairing/bn254/gfp_generic.go new file mode 100644 index 000000000..6e8d8cf94 --- /dev/null +++ b/pairing/bn254/gfp_generic.go @@ -0,0 +1,174 @@ +//go:build (!amd64 && !arm64) || generic +// +build !amd64,!arm64 generic + +package bn254 + +func gfpCarry(a *gfP, head uint64) { + b := &gfP{} + + var carry uint64 + for i, pi := range p2 { + ai := a[i] + bi := ai - pi - carry + b[i] = bi + carry = (pi&^ai | (pi|^ai)&bi) >> 63 + } + carry = carry &^ head + + // If b is negative, then return a. + // Else return b. + carry = -carry + ncarry := ^carry + for i := 0; i < 4; i++ { + a[i] = (a[i] & carry) | (b[i] & ncarry) + } +} + +func gfpNeg(c, a *gfP) { + var carry uint64 + for i, pi := range p2 { + ai := a[i] + ci := pi - ai - carry + c[i] = ci + carry = (ai&^pi | (ai|^pi)&ci) >> 63 + } + gfpCarry(c, 0) +} + +func gfpAdd(c, a, b *gfP) { + var carry uint64 + for i, ai := range a { + bi := b[i] + ci := ai + bi + carry + c[i] = ci + carry = (ai&bi | (ai|bi)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func gfpSub(c, a, b *gfP) { + t := &gfP{} + + var carry uint64 + for i, pi := range p2 { + bi := b[i] + ti := pi - bi - carry + t[i] = ti + carry = (bi&^pi | (bi|^pi)&ti) >> 63 + } + + carry = 0 + for i, ai := range a { + ti := t[i] + ci := ai + ti + carry + c[i] = ci + carry = (ai&ti | (ai|ti)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func mul(a, b [4]uint64) [8]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [32]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 8; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]} +} + +func halfMul(a, b [4]uint64) [4]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [18]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + if i+j > 3 { + break + } + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 4; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [4]uint64{buff[0], buff[4], buff[8], buff[12]} +} + +func gfpMul(c, a, b *gfP) { + T := mul(*a, *b) + m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) + t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) + + var carry uint64 + for i, Ti := range T { + ti := t[i] + zi := Ti + ti + carry + T[i] = zi + carry = (Ti&ti | (Ti|ti)&^zi) >> 63 + } + + *c = gfP{T[4], T[5], T[6], T[7]} + gfpCarry(c, carry) +} diff --git a/pairing/bn254/group.go b/pairing/bn254/group.go new file mode 100644 index 000000000..85ea79b69 --- /dev/null +++ b/pairing/bn254/group.go @@ -0,0 +1,84 @@ +package bn254 + +import ( + "crypto/cipher" + "encoding/hex" + + "github.com/drand/kyber" + "github.com/drand/kyber/group/mod" +) + +type groupG1 struct { + common + *commonSuite + dst []byte +} + +func (g *groupG1) String() string { + b, _ := g.Point().MarshalBinary() + return "bn254.G1: " + hex.EncodeToString(b) +} + +func (g *groupG1) PointLen() int { + return newPointG1(g.dst).MarshalSize() +} + +func (g *groupG1) Point() kyber.Point { + return newPointG1(g.dst) +} + +type groupG2 struct { + common + *commonSuite + dst []byte +} + +func (g *groupG2) String() string { + b, _ := g.Point().MarshalBinary() + return "bn254.G2: " + hex.EncodeToString(b) +} + +func (g *groupG2) PointLen() int { + return newPointG2(g.dst).MarshalSize() +} + +func (g *groupG2) Point() kyber.Point { + return newPointG2(g.dst) +} + +type groupGT struct { + common + *commonSuite +} + +func (g *groupGT) String() string { + b, _ := g.Point().MarshalBinary() + return "bn254.GT: " + hex.EncodeToString(b) +} + +func (g *groupGT) PointLen() int { + return newPointGT().MarshalSize() +} + +func (g *groupGT) Point() kyber.Point { + return newPointGT() +} + +// common functionalities across G1, G2, and GT +type common struct{} + +func (c *common) ScalarLen() int { + return mod.NewInt64(0, Order).MarshalSize() +} + +func (c *common) Scalar() kyber.Scalar { + return mod.NewInt64(0, Order) +} + +func (c *common) PrimeOrder() bool { + return true +} + +func (c *common) NewKey(rand cipher.Stream) kyber.Scalar { + return mod.NewInt64(0, Order).Pick(rand) +} diff --git a/pairing/bn254/lattice.go b/pairing/bn254/lattice.go new file mode 100644 index 000000000..f457cd30f --- /dev/null +++ b/pairing/bn254/lattice.go @@ -0,0 +1,115 @@ +package bn254 + +import ( + "math/big" +) + +var half = new(big.Int).Rsh(Order, 1) + +var curveLattice = &lattice{ + vectors: [][]*big.Int{ + {bigFromBase10("147946756881789319000765030803803410728"), bigFromBase10("147946756881789319010696353538189108491")}, + {bigFromBase10("147946756881789319020627676272574806254"), bigFromBase10("-147946756881789318990833708069417712965")}, + }, + inverse: []*big.Int{ + bigFromBase10("147946756881789318990833708069417712965"), + bigFromBase10("147946756881789319010696353538189108491"), + }, + det: bigFromBase10("43776485743678550444492811490514550177096728800832068687396408373151616991234"), +} + +var targetLattice = &lattice{ + vectors: [][]*big.Int{ + {bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697763"), bigFromBase10("9931322734385697764")}, + {bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848882"), bigFromBase10("-9931322734385697762")}, + {bigFromBase10("-9931322734385697762"), bigFromBase10("-4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("-4965661367192848882")}, + {bigFromBase10("9931322734385697763"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881")}, + }, + inverse: []*big.Int{ + bigFromBase10("734653495049373973658254490726798021314063399421879442165"), + bigFromBase10("147946756881789319000765030803803410728"), + bigFromBase10("-147946756881789319005730692170996259609"), + bigFromBase10("1469306990098747947464455738335385361643788813749140841702"), + }, + det: new(big.Int).Set(Order), +} + +type lattice struct { + vectors [][]*big.Int + inverse []*big.Int + det *big.Int +} + +// decompose takes a scalar mod Order as input and finds a short, positive decomposition of it wrt to the lattice basis. +func (l *lattice) decompose(k *big.Int) []*big.Int { + n := len(l.inverse) + + // Calculate closest vector in lattice to with Babai's rounding. + c := make([]*big.Int, n) + for i := 0; i < n; i++ { + c[i] = new(big.Int).Mul(k, l.inverse[i]) + round(c[i], l.det) + } + + // Transform vectors according to c and subtract . + out := make([]*big.Int, n) + temp := new(big.Int) + + for i := 0; i < n; i++ { + out[i] = new(big.Int) + + for j := 0; j < n; j++ { + temp.Mul(c[j], l.vectors[j][i]) + out[i].Add(out[i], temp) + } + + out[i].Neg(out[i]) + out[i].Add(out[i], l.vectors[0][i]).Add(out[i], l.vectors[0][i]) + } + out[0].Add(out[0], k) + + return out +} + +func (l *lattice) Precompute(add func(i, j uint)) { + n := uint(len(l.vectors)) + total := uint(1) << n + + for i := uint(0); i < n; i++ { + for j := uint(0); j < total; j++ { + if (j>>i)&1 == 1 { + add(i, j) + } + } + } +} + +func (l *lattice) Multi(scalar *big.Int) []uint8 { + decomp := l.decompose(scalar) + + maxLen := 0 + for _, x := range decomp { + if x.BitLen() > maxLen { + maxLen = x.BitLen() + } + } + + out := make([]uint8, maxLen) + for j, x := range decomp { + for i := 0; i < maxLen; i++ { + out[i] += uint8(x.Bit(i)) << uint(j) + } + } + + return out +} + +// round sets num to num/denom rounded to the nearest integer. +func round(num, denom *big.Int) { + r := new(big.Int) + num.DivMod(num, denom, r) + + if r.Cmp(half) == 1 { + num.Add(num, big.NewInt(1)) + } +} diff --git a/pairing/bn254/mul_amd64.h b/pairing/bn254/mul_amd64.h new file mode 100644 index 000000000..9d8e4b37d --- /dev/null +++ b/pairing/bn254/mul_amd64.h @@ -0,0 +1,181 @@ +#define mul(a0,a1,a2,a3, rb, stack) \ + MOVQ a0, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a0, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a0, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a0, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + storeBlock(R8,R9,R10,R11, 0+stack) \ + MOVQ R12, 32+stack \ + \ + MOVQ a1, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a1, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a1, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a1, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 8+stack, R8 \ + ADCQ 16+stack, R9 \ + ADCQ 24+stack, R10 \ + ADCQ 32+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 8+stack) \ + MOVQ R12, 40+stack \ + \ + MOVQ a2, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a2, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a2, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a2, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 16+stack, R8 \ + ADCQ 24+stack, R9 \ + ADCQ 32+stack, R10 \ + ADCQ 40+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 16+stack) \ + MOVQ R12, 48+stack \ + \ + MOVQ a3, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a3, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a3, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a3, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + \ + ADDQ 24+stack, R8 \ + ADCQ 32+stack, R9 \ + ADCQ 40+stack, R10 \ + ADCQ 48+stack, R11 \ + ADCQ $0, R12 \ + storeBlock(R8,R9,R10,R11, 24+stack) \ + MOVQ R12, 56+stack + +#define gfpReduce(stack) \ + \ // m = (T * N') mod R, store m in R8:R9:R10:R11 + MOVQ ·np+0(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ ·np+0(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ ·np+0(SB), AX \ + MULQ 16+stack \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ ·np+0(SB), AX \ + MULQ 24+stack \ + ADDQ AX, R11 \ + \ + MOVQ ·np+8(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R12 \ + MOVQ DX, R13 \ + MOVQ ·np+8(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + MOVQ ·np+8(SB), AX \ + MULQ 16+stack \ + ADDQ AX, R14 \ + \ + ADDQ R12, R9 \ + ADCQ R13, R10 \ + ADCQ R14, R11 \ + \ + MOVQ ·np+16(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R12 \ + MOVQ DX, R13 \ + MOVQ ·np+16(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R13 \ + \ + ADDQ R12, R10 \ + ADCQ R13, R11 \ + \ + MOVQ ·np+24(SB), AX \ + MULQ 0+stack \ + ADDQ AX, R11 \ + \ + storeBlock(R8,R9,R10,R11, 64+stack) \ + \ + \ // m * N + mul(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64+stack, 96+stack) \ + \ + \ // Add the 512-bit intermediate to m*N + loadBlock(96+stack, R8,R9,R10,R11) \ + loadBlock(128+stack, R12,R13,R14,CX) \ + \ + MOVQ $0, AX \ + ADDQ 0+stack, R8 \ + ADCQ 8+stack, R9 \ + ADCQ 16+stack, R10 \ + ADCQ 24+stack, R11 \ + ADCQ 32+stack, R12 \ + ADCQ 40+stack, R13 \ + ADCQ 48+stack, R14 \ + ADCQ 56+stack, CX \ + ADCQ $0, AX \ + \ + gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX) diff --git a/pairing/bn254/mul_arm64.h b/pairing/bn254/mul_arm64.h new file mode 100644 index 000000000..d405eb8f7 --- /dev/null +++ b/pairing/bn254/mul_arm64.h @@ -0,0 +1,133 @@ +#define mul(c0,c1,c2,c3,c4,c5,c6,c7) \ + MUL R1, R5, c0 \ + UMULH R1, R5, c1 \ + MUL R1, R6, R0 \ + ADDS R0, c1 \ + UMULH R1, R6, c2 \ + MUL R1, R7, R0 \ + ADCS R0, c2 \ + UMULH R1, R7, c3 \ + MUL R1, R8, R0 \ + ADCS R0, c3 \ + UMULH R1, R8, c4 \ + ADCS ZR, c4 \ + \ + MUL R2, R5, R1 \ + UMULH R2, R5, R26 \ + MUL R2, R6, R0 \ + ADDS R0, R26 \ + UMULH R2, R6, R27 \ + MUL R2, R7, R0 \ + ADCS R0, R27 \ + UMULH R2, R7, R29 \ + MUL R2, R8, R0 \ + ADCS R0, R29 \ + UMULH R2, R8, c5 \ + ADCS ZR, c5 \ + ADDS R1, c1 \ + ADCS R26, c2 \ + ADCS R27, c3 \ + ADCS R29, c4 \ + ADCS ZR, c5 \ + \ + MUL R3, R5, R1 \ + UMULH R3, R5, R26 \ + MUL R3, R6, R0 \ + ADDS R0, R26 \ + UMULH R3, R6, R27 \ + MUL R3, R7, R0 \ + ADCS R0, R27 \ + UMULH R3, R7, R29 \ + MUL R3, R8, R0 \ + ADCS R0, R29 \ + UMULH R3, R8, c6 \ + ADCS ZR, c6 \ + ADDS R1, c2 \ + ADCS R26, c3 \ + ADCS R27, c4 \ + ADCS R29, c5 \ + ADCS ZR, c6 \ + \ + MUL R4, R5, R1 \ + UMULH R4, R5, R26 \ + MUL R4, R6, R0 \ + ADDS R0, R26 \ + UMULH R4, R6, R27 \ + MUL R4, R7, R0 \ + ADCS R0, R27 \ + UMULH R4, R7, R29 \ + MUL R4, R8, R0 \ + ADCS R0, R29 \ + UMULH R4, R8, c7 \ + ADCS ZR, c7 \ + ADDS R1, c3 \ + ADCS R26, c4 \ + ADCS R27, c5 \ + ADCS R29, c6 \ + ADCS ZR, c7 + +#define gfpReduce() \ + \ // m = (T * N') mod R, store m in R1:R2:R3:R4 + MOVD ·np+0(SB), R17 \ + MOVD ·np+8(SB), R25 \ + MOVD ·np+16(SB), R19 \ + MOVD ·np+24(SB), R20 \ + \ + MUL R9, R17, R1 \ + UMULH R9, R17, R2 \ + MUL R9, R25, R0 \ + ADDS R0, R2 \ + UMULH R9, R25, R3 \ + MUL R9, R19, R0 \ + ADCS R0, R3 \ + UMULH R9, R19, R4 \ + MUL R9, R20, R0 \ + ADCS R0, R4 \ + \ + MUL R10, R17, R21 \ + UMULH R10, R17, R22 \ + MUL R10, R25, R0 \ + ADDS R0, R22 \ + UMULH R10, R25, R23 \ + MUL R10, R19, R0 \ + ADCS R0, R23 \ + ADDS R21, R2 \ + ADCS R22, R3 \ + ADCS R23, R4 \ + \ + MUL R11, R17, R21 \ + UMULH R11, R17, R22 \ + MUL R11, R25, R0 \ + ADDS R0, R22 \ + ADDS R21, R3 \ + ADCS R22, R4 \ + \ + MUL R12, R17, R21 \ + ADDS R21, R4 \ + \ + \ // m * N + loadModulus(R5,R6,R7,R8) \ + mul(R17,R25,R19,R20,R21,R22,R23,R24) \ + \ + \ // Add the 512-bit intermediate to m*N + MOVD ZR, R0 \ + ADDS R9, R17 \ + ADCS R10, R25 \ + ADCS R11, R19 \ + ADCS R12, R20 \ + ADCS R13, R21 \ + ADCS R14, R22 \ + ADCS R15, R23 \ + ADCS R16, R24 \ + ADCS ZR, R0 \ + \ + \ // Our output is R21:R22:R23:R24. Reduce mod p if necessary. + SUBS R5, R21, R10 \ + SBCS R6, R22, R11 \ + SBCS R7, R23, R12 \ + SBCS R8, R24, R13 \ + \ + CSEL CS, R10, R21, R1 \ + CSEL CS, R11, R22, R2 \ + CSEL CS, R12, R23, R3 \ + CSEL CS, R13, R24, R4 diff --git a/pairing/bn254/mul_bmi2_amd64.h b/pairing/bn254/mul_bmi2_amd64.h new file mode 100644 index 000000000..403566c6f --- /dev/null +++ b/pairing/bn254/mul_bmi2_amd64.h @@ -0,0 +1,112 @@ +#define mulBMI2(a0,a1,a2,a3, rb) \ + MOVQ a0, DX \ + MOVQ $0, R13 \ + MULXQ 0+rb, R8, R9 \ + MULXQ 8+rb, AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16+rb, AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24+rb, AX, R12 \ + ADCQ AX, R11 \ + ADCQ $0, R12 \ + ADCQ $0, R13 \ + \ + MOVQ a1, DX \ + MOVQ $0, R14 \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R9 \ + ADCQ BX, R10 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R11 \ + ADCQ BX, R12 \ + ADCQ $0, R13 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + ADCQ $0, R14 \ + \ + MOVQ a2, DX \ + MOVQ $0, CX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + ADCQ $0, R14 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + ADCQ $0, CX \ + \ + MOVQ a3, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + ADCQ $0, CX \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, CX + +#define gfpReduceBMI2() \ + \ // m = (T * N') mod R, store m in R8:R9:R10:R11 + MOVQ ·np+0(SB), DX \ + MULXQ 0(SP), R8, R9 \ + MULXQ 8(SP), AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16(SP), AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24(SP), AX, BX \ + ADCQ AX, R11 \ + \ + MOVQ ·np+8(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R9 \ + ADCQ BX, R10 \ + MULXQ 16(SP), AX, BX \ + ADCQ AX, R11 \ + MULXQ 8(SP), AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + \ + MOVQ ·np+16(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 8(SP), AX, BX \ + ADDQ AX, R11 \ + \ + MOVQ ·np+24(SB), DX \ + MULXQ 0(SP), AX, BX \ + ADDQ AX, R11 \ + \ + storeBlock(R8,R9,R10,R11, 64(SP)) \ + \ + \ // m * N + mulBMI2(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64(SP)) \ + \ + \ // Add the 512-bit intermediate to m*N + MOVQ $0, AX \ + ADDQ 0(SP), R8 \ + ADCQ 8(SP), R9 \ + ADCQ 16(SP), R10 \ + ADCQ 24(SP), R11 \ + ADCQ 32(SP), R12 \ + ADCQ 40(SP), R13 \ + ADCQ 48(SP), R14 \ + ADCQ 56(SP), CX \ + ADCQ $0, AX \ + \ + gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX) diff --git a/pairing/bn254/optate.go b/pairing/bn254/optate.go new file mode 100644 index 000000000..c4a6b6113 --- /dev/null +++ b/pairing/bn254/optate.go @@ -0,0 +1,270 @@ +package bn254 + +func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2) (a, b, c *gfP2, rOut *twistPoint) { + // See the mixed addition algorithm from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + B := (&gfP2{}).Mul(&p.x, &r.t) + + D := (&gfP2{}).Add(&p.y, &r.z) + D.Square(D).Sub(D, r2).Sub(D, &r.t).Mul(D, &r.t) + + H := (&gfP2{}).Sub(B, &r.x) + I := (&gfP2{}).Square(H) + + E := (&gfP2{}).Add(I, I) + E.Add(E, E) + + J := (&gfP2{}).Mul(H, E) + + L1 := (&gfP2{}).Sub(D, &r.y) + L1.Sub(L1, &r.y) + + V := (&gfP2{}).Mul(&r.x, E) + + rOut = &twistPoint{} + rOut.x.Square(L1).Sub(&rOut.x, J).Sub(&rOut.x, V).Sub(&rOut.x, V) + + rOut.z.Add(&r.z, H).Square(&rOut.z).Sub(&rOut.z, &r.t).Sub(&rOut.z, I) + + t := (&gfP2{}).Sub(V, &rOut.x) + t.Mul(t, L1) + t2 := (&gfP2{}).Mul(&r.y, J) + t2.Add(t2, t2) + rOut.y.Sub(t, t2) + + rOut.t.Square(&rOut.z) + + t.Add(&p.y, &rOut.z).Square(t).Sub(t, r2).Sub(t, &rOut.t) + + t2.Mul(L1, &p.x) + t2.Add(t2, t2) + a = (&gfP2{}).Sub(t2, t) + + c = (&gfP2{}).MulScalar(&rOut.z, &q.y) + c.Add(c, c) + + b = (&gfP2{}).Neg(L1) + b.MulScalar(b, &q.x).Add(b, b) + + return +} + +func lineFunctionDouble(r *twistPoint, q *curvePoint) (a, b, c *gfP2, rOut *twistPoint) { + // See the doubling algorithm for a=0 from "Faster Computation of the + // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf + A := (&gfP2{}).Square(&r.x) + B := (&gfP2{}).Square(&r.y) + C := (&gfP2{}).Square(B) + + D := (&gfP2{}).Add(&r.x, B) + D.Square(D).Sub(D, A).Sub(D, C).Add(D, D) + + E := (&gfP2{}).Add(A, A) + E.Add(E, A) + + G := (&gfP2{}).Square(E) + + rOut = &twistPoint{} + rOut.x.Sub(G, D).Sub(&rOut.x, D) + + rOut.z.Add(&r.y, &r.z).Square(&rOut.z).Sub(&rOut.z, B).Sub(&rOut.z, &r.t) + + rOut.y.Sub(D, &rOut.x).Mul(&rOut.y, E) + t := (&gfP2{}).Add(C, C) + t.Add(t, t).Add(t, t) + rOut.y.Sub(&rOut.y, t) + + rOut.t.Square(&rOut.z) + + t.Mul(E, &r.t).Add(t, t) + b = (&gfP2{}).Neg(t) + b.MulScalar(b, &q.x) + + a = (&gfP2{}).Add(&r.x, E) + a.Square(a).Sub(a, A).Sub(a, G) + t.Add(B, B).Add(t, t) + a.Sub(a, t) + + c = (&gfP2{}).Mul(&rOut.z, &r.t) + c.Add(c, c).MulScalar(c, &q.y) + + return +} + +func mulLine(ret *gfP12, a, b, c *gfP2) { + a2 := &gfP6{} + a2.y.Set(a) + a2.z.Set(b) + a2.Mul(a2, &ret.x) + t3 := (&gfP6{}).MulScalar(&ret.y, c) + + t := (&gfP2{}).Add(b, c) + t2 := &gfP6{} + t2.y.Set(a) + t2.z.Set(t) + ret.x.Add(&ret.x, &ret.y) + + ret.y.Set(t3) + + ret.x.Mul(&ret.x, t2).Sub(&ret.x, a2).Sub(&ret.x, &ret.y) + a2.MulTau(a2) + ret.y.Add(&ret.y, a2) +} + +// sixuPlus2NAF is 6u+2 in non-adjacent form. +var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, + 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} + +// miller implements the Miller loop for calculating the Optimal Ate pairing. +// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf +func miller(q *twistPoint, p *curvePoint) *gfP12 { + ret := (&gfP12{}).SetOne() + + aAffine := &twistPoint{} + aAffine.Set(q) + aAffine.MakeAffine() + + bAffine := &curvePoint{} + bAffine.Set(p) + bAffine.MakeAffine() + + minusA := &twistPoint{} + minusA.Neg(aAffine) + + r := &twistPoint{} + r.Set(aAffine) + + r2 := (&gfP2{}).Square(&aAffine.y) + + for i := len(sixuPlus2NAF) - 1; i > 0; i-- { + a, b, c, newR := lineFunctionDouble(r, bAffine) + if i != len(sixuPlus2NAF)-1 { + ret.Square(ret) + } + + mulLine(ret, a, b, c) + r = newR + + switch sixuPlus2NAF[i-1] { + case 1: + a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2) + case -1: + a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2) + default: + continue + } + + mulLine(ret, a, b, c) + r = newR + } + + // In order to calculate Q1 we have to convert q from the sextic twist + // to the full GF(p^12) group, apply the Frobenius there, and convert + // back. + // + // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just + // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) + // where x̄ is the conjugate of x. If we are going to apply the inverse + // isomorphism we need a value with a single coefficient of ω² so we + // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of + // p, 2p-2 is a multiple of six. Therefore we can rewrite as + // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the + // ω². + // + // A similar argument can be made for the y value. + + q1 := &twistPoint{} + q1.x.Conjugate(&aAffine.x).Mul(&q1.x, xiToPMinus1Over3) + q1.y.Conjugate(&aAffine.y).Mul(&q1.y, xiToPMinus1Over2) + q1.z.SetOne() + q1.t.SetOne() + + // For Q2 we are applying the p² Frobenius. The two conjugations cancel + // out and we are left only with the factors from the isomorphism. In + // the case of x, we end up with a pure number which is why + // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We + // ignore this to end up with -Q2. + + minusQ2 := &twistPoint{} + minusQ2.x.MulScalar(&aAffine.x, xiToPSquaredMinus1Over3) + minusQ2.y.Set(&aAffine.y) + minusQ2.z.SetOne() + minusQ2.t.SetOne() + + r2.Square(&q1.y) + a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2) + mulLine(ret, a, b, c) + r = newR + + r2.Square(&minusQ2.y) + a, b, c, _ = lineFunctionAdd(r, minusQ2, bAffine, r2) + mulLine(ret, a, b, c) + + return ret +} + +// finalExponentiation computes the (p¹²-1)/Order-th power of an element of +// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from +// http://cryptojedi.org/papers/dclxvi-20100714.pdf) +func finalExponentiation(in *gfP12) *gfP12 { + t1 := &gfP12{} + + // This is the p^6-Frobenius + t1.x.Neg(&in.x) + t1.y.Set(&in.y) + + inv := &gfP12{} + inv.Invert(in) + t1.Mul(t1, inv) + + t2 := (&gfP12{}).FrobeniusP2(t1) + t1.Mul(t1, t2) + + fp := (&gfP12{}).Frobenius(t1) + fp2 := (&gfP12{}).FrobeniusP2(t1) + fp3 := (&gfP12{}).Frobenius(fp2) + + fu := (&gfP12{}).Exp(t1, u) + fu2 := (&gfP12{}).Exp(fu, u) + fu3 := (&gfP12{}).Exp(fu2, u) + + y3 := (&gfP12{}).Frobenius(fu) + fu2p := (&gfP12{}).Frobenius(fu2) + fu3p := (&gfP12{}).Frobenius(fu3) + y2 := (&gfP12{}).FrobeniusP2(fu2) + + y0 := &gfP12{} + y0.Mul(fp, fp2).Mul(y0, fp3) + + y1 := (&gfP12{}).Conjugate(t1) + y5 := (&gfP12{}).Conjugate(fu2) + y3.Conjugate(y3) + y4 := (&gfP12{}).Mul(fu, fu2p) + y4.Conjugate(y4) + + y6 := (&gfP12{}).Mul(fu3, fu3p) + y6.Conjugate(y6) + + t0 := (&gfP12{}).Square(y6) + t0.Mul(t0, y4).Mul(t0, y5) + t1.Mul(y3, y5).Mul(t1, t0) + t0.Mul(t0, y2) + t1.Square(t1).Mul(t1, t0).Square(t1) + t0.Mul(t1, y1) + t1.Mul(t1, y0) + t0.Square(t0).Mul(t0, t1) + + return t0 +} + +func optimalAte(a *twistPoint, b *curvePoint) *gfP12 { + e := miller(a, b) + ret := finalExponentiation(e) + + if a.IsInfinity() || b.IsInfinity() { + ret.SetOne() + } + return ret +} diff --git a/pairing/bn254/point.go b/pairing/bn254/point.go new file mode 100644 index 000000000..b50d50906 --- /dev/null +++ b/pairing/bn254/point.go @@ -0,0 +1,723 @@ +package bn254 + +import ( + "crypto/cipher" + "crypto/subtle" + "errors" + "io" + "math/big" + + "github.com/drand/kyber" + "github.com/drand/kyber/group/mod" + "golang.org/x/crypto/sha3" +) + +var marshalPointID1 = [8]byte{'b', 'n', '2', '5', '4', '.', 'g', '1'} +var marshalPointID2 = [8]byte{'b', 'n', '2', '5', '4', '.', 'g', '2'} +var marshalPointIDT = [8]byte{'b', 'n', '2', '5', '4', '.', 'g', 't'} + +type pointG1 struct { + g *curvePoint + dst []byte +} + +func newPointG1(dst []byte) *pointG1 { + p := &pointG1{g: &curvePoint{}, dst: dst} + return p +} + +func (p *pointG1) Equal(q kyber.Point) bool { + x, _ := p.MarshalBinary() + y, _ := q.MarshalBinary() + return subtle.ConstantTimeCompare(x, y) == 1 +} + +func (p *pointG1) Null() kyber.Point { + p.g.SetInfinity() + return p +} + +func (p *pointG1) Base() kyber.Point { + p.g.Set(curveGen) + return p +} + +func (p *pointG1) Pick(rand cipher.Stream) kyber.Point { + s := mod.NewInt64(0, Order).Pick(rand) + p.Base() + p.g.Mul(p.g, &s.(*mod.Int).V) + return p +} + +func (p *pointG1) Set(q kyber.Point) kyber.Point { + x := q.(*pointG1).g + p.g.Set(x) + return p +} + +// Clone makes a hard copy of the point +func (p *pointG1) Clone() kyber.Point { + q := newPointG1(p.dst) + q.g = p.g.Clone() + return q +} + +func (p *pointG1) EmbedLen() int { + panic("bn254.G1: unsupported operation") +} + +func (p *pointG1) Embed(data []byte, rand cipher.Stream) kyber.Point { + // XXX: An approach to implement this is: + // - Encode data as the x-coordinate of a point on y²=x³+3 where len(data) + // is stored in the least significant byte of x and the rest is being + // filled with random values, i.e., x = rand || data || len(data). + // - Use the Tonelli-Shanks algorithm to compute the y-coordinate. + // - Convert the new point to Jacobian coordinates and set it as p. + panic("bn254.G1: unsupported operation") +} + +func (p *pointG1) Data() ([]byte, error) { + panic("bn254.G1: unsupported operation") +} + +func (p *pointG1) Add(a, b kyber.Point) kyber.Point { + x := a.(*pointG1).g + y := b.(*pointG1).g + p.g.Add(x, y) // p = a + b + return p +} + +func (p *pointG1) Sub(a, b kyber.Point) kyber.Point { + q := newPointG1(p.dst) + return p.Add(a, q.Neg(b)) +} + +func (p *pointG1) Neg(q kyber.Point) kyber.Point { + x := q.(*pointG1).g + p.g.Neg(x) + return p +} + +func (p *pointG1) Mul(s kyber.Scalar, q kyber.Point) kyber.Point { + if q == nil { + q = newPointG1(p.dst).Base() + } + t := s.(*mod.Int).V + r := q.(*pointG1).g + p.g.Mul(r, &t) + return p +} + +func (p *pointG1) MarshalBinary() ([]byte, error) { + // Clone is required as we change the point + p = p.Clone().(*pointG1) + + n := p.ElementSize() + // Take a copy so that p is not written to, so calls to MarshalBinary + // are threadsafe. + pgtemp := *p.g + pgtemp.MakeAffine() + ret := make([]byte, p.MarshalSize()) + if pgtemp.IsInfinity() { + return ret, nil + } + tmp := &gfP{} + montDecode(tmp, &pgtemp.x) + tmp.Marshal(ret) + montDecode(tmp, &pgtemp.y) + tmp.Marshal(ret[n:]) + return ret, nil +} + +func (p *pointG1) MarshalID() [8]byte { + return marshalPointID1 +} + +func (p *pointG1) MarshalTo(w io.Writer) (int, error) { + buf, err := p.MarshalBinary() + if err != nil { + return 0, err + } + return w.Write(buf) +} + +func (p *pointG1) UnmarshalBinary(buf []byte) error { + n := p.ElementSize() + if len(buf) < p.MarshalSize() { + return errors.New("bn254.G1: not enough data") + } + if p.g == nil { + p.g = &curvePoint{} + } else { + p.g.x, p.g.y = gfP{0}, gfP{0} + } + + p.g.x.Unmarshal(buf) + p.g.y.Unmarshal(buf[n:]) + montEncode(&p.g.x, &p.g.x) + montEncode(&p.g.y, &p.g.y) + + zero := gfP{0} + if p.g.x == zero && p.g.y == zero { + // This is the point at infinity + p.g.y = *newGFp(1) + p.g.z = gfP{0} + p.g.t = gfP{0} + } else { + p.g.z = *newGFp(1) + p.g.t = *newGFp(1) + } + + if !p.g.IsOnCurve() { + return errors.New("bn254.G1: malformed point") + } + + return nil +} + +func (p *pointG1) UnmarshalFrom(r io.Reader) (int, error) { + buf := make([]byte, p.MarshalSize()) + n, err := io.ReadFull(r, buf) + if err != nil { + return n, err + } + return n, p.UnmarshalBinary(buf) +} + +func (p *pointG1) MarshalSize() int { + return 2 * p.ElementSize() +} + +func (p *pointG1) ElementSize() int { + return 256 / 8 +} + +func (p *pointG1) String() string { + return "bn254.G1" + p.g.String() +} + +func (p *pointG1) Hash(m []byte) kyber.Point { + return hashToPoint(p.dst, m) +} + +func hashToPoint(domain, m []byte) kyber.Point { + e0, e1 := hashToField(domain, m) + p0 := mapToPoint(domain, e0) + p1 := mapToPoint(domain, e1) + p := p0.Add(p0, p1) + return p +} + +func hashToField(domain, m []byte) (*gfP, *gfP) { + const u = 48 + _msg := expandMsgXmdKeccak256(domain, m, 2*u) + x, y := new(big.Int), new(big.Int) + x.SetBytes(_msg[0:48]).Mod(x, p) + y.SetBytes(_msg[48:96]).Mod(y, p) + gx, gy := &gfP{}, &gfP{} + gx.Unmarshal(zeroPadBytes(x.Bytes(), 32)) + gy.Unmarshal(zeroPadBytes(y.Bytes(), 32)) + montEncode(gx, gx) + montEncode(gy, gy) + return gx, gy +} + +// `mapToPoint` implements the general Shallue-van de Woestijne mapping to BN254 G1 +// RFC9380, 6.6.1. https://datatracker.ietf.org/doc/html/rfc9380#name-shallue-van-de-woestijne-me +func mapToPoint(domain []byte, u *gfP) kyber.Point { + tv1 := &gfP{} + tv1.Set(u) + gfpMul(tv1, tv1, tv1) + gfpMul(tv1, tv1, c1) + tv2 := &gfP{} + gfpAdd(tv2, newGFp(1), tv1) + negTv1 := &gfP{} + gfpNeg(negTv1, tv1) + gfpAdd(tv1, newGFp(1), negTv1) + tv3 := &gfP{} + gfpMul(tv3, tv1, tv2) + tv3.Invert(tv3) + tv5 := &gfP{} + gfpMul(tv5, u, tv1) + gfpMul(tv5, tv5, tv3) + gfpMul(tv5, tv5, c3) + x1 := &gfP{} + gfpSub(x1, c2, tv5) + x2 := &gfP{} + gfpAdd(x2, c2, tv5) + tv7 := &gfP{} + gfpMul(tv7, tv2, tv2) + tv8 := &gfP{} + gfpMul(tv8, tv7, tv3) + x3 := &gfP{} + gfpMul(x3, tv8, tv8) + gfpMul(x3, c4, x3) + gfpAdd(x3, newGFp(1), x3) + + x, y := &gfP{}, &gfP{} + if legendre(g(x1)) == 1 { + x = x1 + y.Sqrt(g(x1)) + } else if legendre(g(x2)) == 1 { + x = x2 + y.Sqrt(g(x2)) + } else { + x = x3 + y.Sqrt(g(x3)) + } + if sgn0(u) != sgn0(y) { + gfpNeg(y, y) + } + + p := newPointG1(domain).Base().(*pointG1) + p.g.x.Set(x) + p.g.y.Set(y) + return p +} + +// `expandMsgXmdKeccak256` implements expand_message_xmd from IETF RFC9380 Sec 5.3.1 +// Borrowed from: https://github.com/kilic/bls12-381/blob/master/hash_to_field.go +func expandMsgXmdKeccak256(domain, msg []byte, outLen int) []byte { + h := sha3.NewLegacyKeccak256() + domainLen := uint8(len(domain)) + if domainLen > 255 { + panic("invalid domain length") + } + // DST_prime = DST || I2OSP(len(DST), 1) + // b_0 = H(Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime) + _, _ = h.Write(make([]byte, h.BlockSize())) + _, _ = h.Write(msg) + _, _ = h.Write([]byte{uint8(outLen >> 8), uint8(outLen)}) + _, _ = h.Write([]byte{0}) + _, _ = h.Write(domain) + _, _ = h.Write([]byte{domainLen}) + b0 := h.Sum(nil) + + // b_1 = H(b_0 || I2OSP(1, 1) || DST_prime) + h.Reset() + _, _ = h.Write(b0) + _, _ = h.Write([]byte{1}) + _, _ = h.Write(domain) + _, _ = h.Write([]byte{domainLen}) + b1 := h.Sum(nil) + + // b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + ell := (outLen + h.Size() - 1) / h.Size() + bi := b1 + out := make([]byte, outLen) + for i := 1; i < ell; i++ { + h.Reset() + // b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + tmp := make([]byte, h.Size()) + for j := 0; j < h.Size(); j++ { + tmp[j] = b0[j] ^ bi[j] + } + _, _ = h.Write(tmp) + _, _ = h.Write([]byte{1 + uint8(i)}) + _, _ = h.Write(domain) + _, _ = h.Write([]byte{domainLen}) + + // b_1 || ... || b_(ell - 1) + copy(out[(i-1)*h.Size():i*h.Size()], bi[:]) + bi = h.Sum(nil) + } + // b_ell + copy(out[(ell-1)*h.Size():], bi[:]) + return out[:outLen] +} + +type pointG2 struct { + g *twistPoint + dst []byte +} + +func newPointG2(dst []byte) *pointG2 { + p := &pointG2{g: &twistPoint{}, dst: dst} + return p +} + +func (p *pointG2) Equal(q kyber.Point) bool { + x, _ := p.MarshalBinary() + y, _ := q.MarshalBinary() + return subtle.ConstantTimeCompare(x, y) == 1 +} + +func (p *pointG2) Null() kyber.Point { + p.g.SetInfinity() + return p +} + +func (p *pointG2) Base() kyber.Point { + p.g.Set(twistGen) + return p +} + +func (p *pointG2) Pick(rand cipher.Stream) kyber.Point { + s := mod.NewInt64(0, Order).Pick(rand) + p.Base() + p.g.Mul(p.g, &s.(*mod.Int).V) + return p +} + +func (p *pointG2) Set(q kyber.Point) kyber.Point { + x := q.(*pointG2).g + p.g.Set(x) + return p +} + +// Clone makes a hard copy of the field +func (p *pointG2) Clone() kyber.Point { + q := newPointG2(p.dst) + q.g = p.g.Clone() + return q +} + +func (p *pointG2) EmbedLen() int { + panic("bn254.G2: unsupported operation") +} + +func (p *pointG2) Embed(data []byte, rand cipher.Stream) kyber.Point { + panic("bn254.G2: unsupported operation") +} + +func (p *pointG2) Data() ([]byte, error) { + panic("bn254.G2: unsupported operation") +} + +func (p *pointG2) Add(a, b kyber.Point) kyber.Point { + x := a.(*pointG2).g + y := b.(*pointG2).g + p.g.Add(x, y) // p = a + b + return p +} + +func (p *pointG2) Sub(a, b kyber.Point) kyber.Point { + q := newPointG2(p.dst) + return p.Add(a, q.Neg(b)) +} + +func (p *pointG2) Neg(q kyber.Point) kyber.Point { + x := q.(*pointG2).g + p.g.Neg(x) + return p +} + +func (p *pointG2) Mul(s kyber.Scalar, q kyber.Point) kyber.Point { + if q == nil { + q = newPointG2(p.dst).Base() + } + t := s.(*mod.Int).V + r := q.(*pointG2).g + p.g.Mul(r, &t) + return p +} + +func (p *pointG2) MarshalBinary() ([]byte, error) { + // Clone is required as we change the point during the operation + p = p.Clone().(*pointG2) + + n := p.ElementSize() + if p.g == nil { + p.g = &twistPoint{} + } + + p.g.MakeAffine() + + ret := make([]byte, p.MarshalSize()) + if p.g.IsInfinity() { + return ret, nil + } + + temp := &gfP{} + montDecode(temp, &p.g.x.x) + temp.Marshal(ret[0*n:]) + montDecode(temp, &p.g.x.y) + temp.Marshal(ret[1*n:]) + montDecode(temp, &p.g.y.x) + temp.Marshal(ret[2*n:]) + montDecode(temp, &p.g.y.y) + temp.Marshal(ret[3*n:]) + + return ret, nil +} + +func (p *pointG2) MarshalID() [8]byte { + return marshalPointID2 +} + +func (p *pointG2) MarshalTo(w io.Writer) (int, error) { + buf, err := p.MarshalBinary() + if err != nil { + return 0, err + } + return w.Write(buf) +} + +func (p *pointG2) UnmarshalBinary(buf []byte) error { + n := p.ElementSize() + if p.g == nil { + p.g = &twistPoint{} + } + + if len(buf) < p.MarshalSize() { + return errors.New("bn254.G2: not enough data") + } + + p.g.x.x.Unmarshal(buf[0*n:]) + p.g.x.y.Unmarshal(buf[1*n:]) + p.g.y.x.Unmarshal(buf[2*n:]) + p.g.y.y.Unmarshal(buf[3*n:]) + montEncode(&p.g.x.x, &p.g.x.x) + montEncode(&p.g.x.y, &p.g.x.y) + montEncode(&p.g.y.x, &p.g.y.x) + montEncode(&p.g.y.y, &p.g.y.y) + + if p.g.x.IsZero() && p.g.y.IsZero() { + // This is the point at infinity. + p.g.y.SetOne() + p.g.z.SetZero() + p.g.t.SetZero() + } else { + p.g.z.SetOne() + p.g.t.SetOne() + + if !p.g.IsOnCurve() { + return errors.New("bn254.G2: malformed point") + } + } + return nil +} + +func (p *pointG2) UnmarshalFrom(r io.Reader) (int, error) { + buf := make([]byte, p.MarshalSize()) + n, err := io.ReadFull(r, buf) + if err != nil { + return n, err + } + return n, p.UnmarshalBinary(buf) +} + +func (p *pointG2) MarshalSize() int { + return 4 * p.ElementSize() +} + +func (p *pointG2) ElementSize() int { + return 256 / 8 +} + +func (p *pointG2) String() string { + return "bn254.G2" + p.g.String() +} + +type pointGT struct { + g *gfP12 +} + +func newPointGT() *pointGT { + p := &pointGT{g: &gfP12{}} + return p +} + +func (p *pointGT) Equal(q kyber.Point) bool { + x, _ := p.MarshalBinary() + y, _ := q.MarshalBinary() + return subtle.ConstantTimeCompare(x, y) == 1 +} + +func (p *pointGT) Null() kyber.Point { + // TODO: This can be a precomputed constant + p.Pair(newPointG1([]byte{}).Null(), newPointG2([]byte{}).Null()) + return p +} + +func (p *pointGT) Base() kyber.Point { + // TODO: This can be a precomputed constant + p.Pair(newPointG1([]byte{}).Base(), newPointG2([]byte{}).Base()) + return p +} + +func (p *pointGT) Pick(rand cipher.Stream) kyber.Point { + s := mod.NewInt64(0, Order).Pick(rand) + p.Base() + p.g.Exp(p.g, &s.(*mod.Int).V) + return p +} + +func (p *pointGT) Set(q kyber.Point) kyber.Point { + x := q.(*pointGT).g + p.g.Set(x) + return p +} + +// Clone makes a hard copy of the point +func (p *pointGT) Clone() kyber.Point { + q := newPointGT() + q.g = p.g.Clone() + return q +} + +func (p *pointGT) EmbedLen() int { + panic("bn254.GT: unsupported operation") +} + +func (p *pointGT) Embed(data []byte, rand cipher.Stream) kyber.Point { + panic("bn254.GT: unsupported operation") +} + +func (p *pointGT) Data() ([]byte, error) { + panic("bn254.GT: unsupported operation") +} + +func (p *pointGT) Add(a, b kyber.Point) kyber.Point { + x := a.(*pointGT).g + y := b.(*pointGT).g + p.g.Mul(x, y) + return p +} + +func (p *pointGT) Sub(a, b kyber.Point) kyber.Point { + q := newPointGT() + return p.Add(a, q.Neg(b)) +} + +func (p *pointGT) Neg(q kyber.Point) kyber.Point { + x := q.(*pointGT).g + p.g.Conjugate(x) + return p +} + +func (p *pointGT) Mul(s kyber.Scalar, q kyber.Point) kyber.Point { + if q == nil { + q = newPointGT().Base() + } + t := s.(*mod.Int).V + r := q.(*pointGT).g + p.g.Exp(r, &t) + return p +} + +func (p *pointGT) MarshalBinary() ([]byte, error) { + n := p.ElementSize() + ret := make([]byte, p.MarshalSize()) + temp := &gfP{} + + montDecode(temp, &p.g.x.x.x) + temp.Marshal(ret[0*n:]) + montDecode(temp, &p.g.x.x.y) + temp.Marshal(ret[1*n:]) + montDecode(temp, &p.g.x.y.x) + temp.Marshal(ret[2*n:]) + montDecode(temp, &p.g.x.y.y) + temp.Marshal(ret[3*n:]) + montDecode(temp, &p.g.x.z.x) + temp.Marshal(ret[4*n:]) + montDecode(temp, &p.g.x.z.y) + temp.Marshal(ret[5*n:]) + montDecode(temp, &p.g.y.x.x) + temp.Marshal(ret[6*n:]) + montDecode(temp, &p.g.y.x.y) + temp.Marshal(ret[7*n:]) + montDecode(temp, &p.g.y.y.x) + temp.Marshal(ret[8*n:]) + montDecode(temp, &p.g.y.y.y) + temp.Marshal(ret[9*n:]) + montDecode(temp, &p.g.y.z.x) + temp.Marshal(ret[10*n:]) + montDecode(temp, &p.g.y.z.y) + temp.Marshal(ret[11*n:]) + + return ret, nil +} + +func (p *pointGT) MarshalID() [8]byte { + return marshalPointIDT +} + +func (p *pointGT) MarshalTo(w io.Writer) (int, error) { + buf, err := p.MarshalBinary() + if err != nil { + return 0, err + } + return w.Write(buf) +} + +func (p *pointGT) UnmarshalBinary(buf []byte) error { + n := p.ElementSize() + if len(buf) < p.MarshalSize() { + return errors.New("bn254.GT: not enough data") + } + + if p.g == nil { + p.g = &gfP12{} + } + + p.g.x.x.x.Unmarshal(buf[0*n:]) + p.g.x.x.y.Unmarshal(buf[1*n:]) + p.g.x.y.x.Unmarshal(buf[2*n:]) + p.g.x.y.y.Unmarshal(buf[3*n:]) + p.g.x.z.x.Unmarshal(buf[4*n:]) + p.g.x.z.y.Unmarshal(buf[5*n:]) + p.g.y.x.x.Unmarshal(buf[6*n:]) + p.g.y.x.y.Unmarshal(buf[7*n:]) + p.g.y.y.x.Unmarshal(buf[8*n:]) + p.g.y.y.y.Unmarshal(buf[9*n:]) + p.g.y.z.x.Unmarshal(buf[10*n:]) + p.g.y.z.y.Unmarshal(buf[11*n:]) + montEncode(&p.g.x.x.x, &p.g.x.x.x) + montEncode(&p.g.x.x.y, &p.g.x.x.y) + montEncode(&p.g.x.y.x, &p.g.x.y.x) + montEncode(&p.g.x.y.y, &p.g.x.y.y) + montEncode(&p.g.x.z.x, &p.g.x.z.x) + montEncode(&p.g.x.z.y, &p.g.x.z.y) + montEncode(&p.g.y.x.x, &p.g.y.x.x) + montEncode(&p.g.y.x.y, &p.g.y.x.y) + montEncode(&p.g.y.y.x, &p.g.y.y.x) + montEncode(&p.g.y.y.y, &p.g.y.y.y) + montEncode(&p.g.y.z.x, &p.g.y.z.x) + montEncode(&p.g.y.z.y, &p.g.y.z.y) + + // TODO: check if point is on curve + + return nil +} + +func (p *pointGT) UnmarshalFrom(r io.Reader) (int, error) { + buf := make([]byte, p.MarshalSize()) + n, err := io.ReadFull(r, buf) + if err != nil { + return n, err + } + return n, p.UnmarshalBinary(buf) +} + +func (p *pointGT) MarshalSize() int { + return 12 * p.ElementSize() +} + +func (p *pointGT) ElementSize() int { + return 256 / 8 +} + +func (p *pointGT) String() string { + return "bn254.GT" + p.g.String() +} + +func (p *pointGT) Finalize() kyber.Point { + buf := finalExponentiation(p.g) + p.g.Set(buf) + return p +} + +func (p *pointGT) Miller(p1, p2 kyber.Point) kyber.Point { + a := p1.(*pointG1).g + b := p2.(*pointG2).g + p.g.Set(miller(b, a)) + return p +} + +func (p *pointGT) Pair(p1, p2 kyber.Point) kyber.Point { + a := p1.(*pointG1).g + b := p2.(*pointG2).g + p.g.Set(optimalAte(b, a)) + return p +} diff --git a/pairing/bn254/point_test.go b/pairing/bn254/point_test.go new file mode 100644 index 000000000..2275b996d --- /dev/null +++ b/pairing/bn254/point_test.go @@ -0,0 +1,208 @@ +package bn254 + +import ( + "bytes" + "encoding/hex" + "errors" + "testing" + + "golang.org/x/crypto/sha3" +) + +func TestPointG1_HashToPoint(t *testing.T) { + domain := []byte("domain_separation_tag_test_12345") + + // reference test 1 + p := newPointG1(domain).Hash([]byte("The Times 03/Jan/2009 Chancellor on brink of second bailout for banks")) + pBuf, err := p.MarshalBinary() + if err != nil { + t.Error(err) + } + refBuf, err := hex.DecodeString("13af4ace8febc1ec800f7d33d66868310516bce9cb1b7f7c68607f9ba6dba92c1823b8f13feeb8dad6b152eb2bbefbe59452f9519c88230b55d0b699498db6f1") + if err != nil { + t.Error(err) + } + if !bytes.Equal(pBuf, refBuf) { + t.Error("hash does not match reference") + } + + // reference test 2 + buf2, err := hex.DecodeString("e0a05cbb37fd6c159732a8c57b981773f7480695328b674d8a9cc083377f1811") + if err != nil { + t.Error(err) + } + p2 := newPointG1(domain).Hash(buf2) + p2Buf, err := p2.MarshalBinary() + if err != nil { + t.Error(err) + } + refBuf2, err := hex.DecodeString("07abd743dc93dfa3a8ee4ab449b1657dc6232c589612b23a54ea461c7232101e2533badbee56e8457731fc35bb7630236623e4614e4f8acb4a0c3282df58a289") + if err != nil { + t.Error(err) + } + if !bytes.Equal(p2Buf, refBuf2) { + t.Error("hash does not match reference") + } +} + +func TestExpandMsg(t *testing.T) { + dst := []byte("BLS_SIG_BN254G1_XMD:KECCAK-256_SSWU_RO_NUL_") + msg, err := hex.DecodeString("af6c1f30b2f3f2fd448193f90d6fb55b544a") + if err != nil { + t.Error("decode errored", err.Error()) + } + + expanded := expandMsgXmdKeccak256( + dst, + msg, + 96, + ) + if err != nil { + t.Error("expandMsgXmdKeccak256 errored", err.Error()) + } + + // Output from Solidity & ts implementation in bls-bn254 + if hex.EncodeToString(expanded) != "bd365d9672926bbb6887f8c0ce88d1edc0c20bd46f6af54e80c7edc15ac1c5eba9e754994af715195aa8acb3f21febae2b9626bc1b06c185922455908d1c8db3d370fe339995718e344af3add0aa77d3bd48d0d9f3ebe26b88cbb393325c1c6e" { + t.Error("expandMsgXmdKeccak256 does not match ref", hex.EncodeToString(expanded)) + } + + // Sanity check against gnark's implementation + gnarkExpanded, err := gnarkExpandMsgXmd(msg, dst, 96) + if err != nil { + t.Error("gnarkExpandMsgXmd errored", err.Error()) + } + if hex.EncodeToString(expanded) != hex.EncodeToString(gnarkExpanded) { + t.Error("expandMsgXmdKeccak256 did not match gnark implementation") + } +} + +func TestHashToField(t *testing.T) { + dst := []byte("BLS_SIG_BN254G1_XMD:KECCAK-256_SSWU_RO_NUL_") + for i, testVector := range hashToFieldTestVectors { + _msg, err := hex.DecodeString(testVector.Msg) + if err != nil { + t.Error("decode errored", err.Error()) + } + + x, y := hashToField( + dst, + _msg, + ) + + if x.String() != testVector.RefX { + t.Errorf("[%d] hashToField x does not match ref %s != %s", i, x, testVector.RefX) + } + if y.String() != testVector.RefY { + t.Errorf("[%d] hashToField y does not match ref %s != %s", i, y, testVector.RefY) + } + } +} + +func TestMapToPoint(t *testing.T) { + dst := []byte("BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_") + + for i, testVector := range mapToPointTestVectors { + u := newGFpFromBase10(testVector.U) + pRef := newPointG1(dst).Base().(*pointG1) + pRef.g.x.Set(newGFpFromBase10(testVector.RefX)) + pRef.g.y.Set(newGFpFromBase10(testVector.RefY)) + + p := mapToPoint(dst, u).(*pointG1) + + if !p.Equal(pRef) { + t.Errorf("[%d] point does not match ref (%s != %s)", i, p.String(), pRef.String()) + } + } +} + +// Borrowed from: https://github.com/Consensys/gnark-crypto/blob/18aa16f0fde4c13d8a7d3806bf13d70b6b5d4cb6/field/hash/hashutils.go +// The first line instantiating the hashing function has been changed from sha256 to keccak256. +// This is here to sanity check against our actual implementation. +// +// ExpandMsgXmd expands msg to a slice of lenInBytes bytes. +// https://datatracker.ietf.org/doc/html/rfc9380#name-expand_message_xmd +// https://datatracker.ietf.org/doc/html/rfc9380#name-utility-functions (I2OSP/O2ISP) +func gnarkExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { + + h := sha3.NewLegacyKeccak256() + ell := (lenInBytes + h.Size() - 1) / h.Size() // ceil(len_in_bytes / b_in_bytes) + if ell > 255 { + return nil, errors.New("invalid lenInBytes") + } + if len(dst) > 255 { + return nil, errors.New("invalid domain size (>255 bytes)") + } + sizeDomain := uint8(len(dst)) + + // Z_pad = I2OSP(0, r_in_bytes) + // l_i_b_str = I2OSP(len_in_bytes, 2) + // DST_prime = DST ∥ I2OSP(len(DST), 1) + // b₀ = H(Z_pad ∥ msg ∥ l_i_b_str ∥ I2OSP(0, 1) ∥ DST_prime) + h.Reset() + if _, err := h.Write(make([]byte, h.BlockSize())); err != nil { + return nil, err + } + if _, err := h.Write(msg); err != nil { + return nil, err + } + if _, err := h.Write([]byte{uint8(lenInBytes >> 8), uint8(lenInBytes), uint8(0)}); err != nil { + return nil, err + } + if _, err := h.Write(dst); err != nil { + return nil, err + } + if _, err := h.Write([]byte{sizeDomain}); err != nil { + return nil, err + } + b0 := h.Sum(nil) + + // b₁ = H(b₀ ∥ I2OSP(1, 1) ∥ DST_prime) + h.Reset() + if _, err := h.Write(b0); err != nil { + return nil, err + } + if _, err := h.Write([]byte{uint8(1)}); err != nil { + return nil, err + } + if _, err := h.Write(dst); err != nil { + return nil, err + } + if _, err := h.Write([]byte{sizeDomain}); err != nil { + return nil, err + } + b1 := h.Sum(nil) + + res := make([]byte, lenInBytes) + copy(res[:h.Size()], b1) + + for i := 2; i <= ell; i++ { + // b_i = H(strxor(b₀, b_(i - 1)) ∥ I2OSP(i, 1) ∥ DST_prime) + h.Reset() + strxor := make([]byte, h.Size()) + for j := 0; j < h.Size(); j++ { + strxor[j] = b0[j] ^ b1[j] + } + if _, err := h.Write(strxor); err != nil { + return nil, err + } + if _, err := h.Write([]byte{uint8(i)}); err != nil { + return nil, err + } + if _, err := h.Write(dst); err != nil { + return nil, err + } + if _, err := h.Write([]byte{sizeDomain}); err != nil { + return nil, err + } + b1 = h.Sum(nil) + copy(res[h.Size()*(i-1):min(h.Size()*i, len(res))], b1) + } + return res, nil +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/pairing/bn254/suite.go b/pairing/bn254/suite.go new file mode 100644 index 000000000..98e8f96bd --- /dev/null +++ b/pairing/bn254/suite.go @@ -0,0 +1,218 @@ +// package bn254 implements a particular bilinear group. +// +// Bilinear groups are the basis of many of the new cryptographic protocols that +// have been proposed over the past decade. They consist of a triplet of groups +// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ +// is a generator of the respective group). That function is called a pairing +// function. +// +// This package specifically implements the Optimal Ate pairing over a 256-bit +// Barreto-Naehrig curve as described in +// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible +// with the implementation described in that paper. +// +// This package previously claimed to operate at a 128-bit security level. +// However, recent improvements in attacks mean that is no longer true. See +// https://moderncrypto.org/mail-archive/curves/2016/000740.html. +package bn254 + +import ( + "crypto/cipher" + "hash" + "io" + "reflect" + + "github.com/drand/kyber" + "github.com/drand/kyber/util/random" + "github.com/drand/kyber/xof/blake2xb" + "go.dedis.ch/fixbuf" + "golang.org/x/crypto/sha3" +) + +// Suite implements the pairing.Suite interface for the BN254 bilinear pairing. +type Suite struct { + *commonSuite + g1 *groupG1 + g2 *groupG2 + gt *groupGT +} + +func newDefaultDomainG1() []byte { + return []byte("BN254G1_XMD:KECCAK-256_SSWU_RO_") +} + +func newDefaultDomainG2() []byte { + return []byte("BN254G2_XMD:KECCAK-256_SSWU_RO_") +} + +// NewSuite generates and returns a new BN254 pairing suite. +func NewSuite() *Suite { + s := &Suite{commonSuite: &commonSuite{}} + s.g1 = &groupG1{ + commonSuite: s.commonSuite, + dst: newDefaultDomainG1(), + } + s.g2 = &groupG2{ + commonSuite: s.commonSuite, + dst: newDefaultDomainG2(), + } + s.gt = &groupGT{commonSuite: s.commonSuite} + return s +} + +// NewSuiteG1 returns a G1 suite. +func NewSuiteG1() *Suite { + s := NewSuite() + s.commonSuite.Group = &groupG1{commonSuite: &commonSuite{}} + return s +} + +// NewSuiteG2 returns a G2 suite. +func NewSuiteG2() *Suite { + s := NewSuite() + s.commonSuite.Group = &groupG2{commonSuite: &commonSuite{}} + return s +} + +// NewSuiteGT returns a GT suite. +func NewSuiteGT() *Suite { + s := NewSuite() + s.commonSuite.Group = &groupGT{commonSuite: &commonSuite{}} + return s +} + +// NewSuiteRand generates and returns a new BN254 suite seeded by the +// given cipher stream. +func NewSuiteRand(rand cipher.Stream) *Suite { + s := &Suite{commonSuite: &commonSuite{s: rand}} + s.g1 = &groupG1{ + commonSuite: s.commonSuite, + dst: newDefaultDomainG1(), + } + s.g2 = &groupG2{ + commonSuite: s.commonSuite, + dst: newDefaultDomainG2(), + } + s.gt = &groupGT{commonSuite: s.commonSuite} + return s +} + +// Set G1 DST +func (s *Suite) SetDomainG1(dst []byte) { + newDST := make([]byte, len(dst)) + copy(newDST, dst) + s.g1.dst = newDST +} + +// Set G2 DST +func (s *Suite) SetDomainG2(dst []byte) { + newDST := make([]byte, len(dst)) + copy(newDST, dst) + s.g2.dst = newDST +} + +// G1 returns the group G1 of the BN254 pairing. +func (s *Suite) G1() kyber.Group { + return s.g1 +} + +// G2 returns the group G2 of the BN254 pairing. +func (s *Suite) G2() kyber.Group { + return s.g2 +} + +// GT returns the group GT of the BN254 pairing. +func (s *Suite) GT() kyber.Group { + return s.gt +} + +// Pair takes the points p1 and p2 in groups G1 and G2, respectively, as input +// and computes their pairing in GT. +func (s *Suite) Pair(p1 kyber.Point, p2 kyber.Point) kyber.Point { + return s.GT().Point().(*pointGT).Pair(p1, p2) +} + +func (s *Suite) ValidatePairing(p1, p2, inv1, inv2 kyber.Point) bool { + p2.(*pointG2).g.MakeAffine() + inv2.(*pointG2).g.MakeAffine() + return s.Pair(p1, p2).Equal(s.Pair(inv1, inv2)) +} + +// Not used other than for reflect.TypeOf() +var aScalar kyber.Scalar +var aPoint kyber.Point +var aPointG1 pointG1 +var aPointG2 pointG2 +var aPointGT pointGT + +var tScalar = reflect.TypeOf(&aScalar).Elem() +var tPoint = reflect.TypeOf(&aPoint).Elem() +var tPointG1 = reflect.TypeOf(&aPointG1).Elem() +var tPointG2 = reflect.TypeOf(&aPointG2).Elem() +var tPointGT = reflect.TypeOf(&aPointGT).Elem() + +type commonSuite struct { + s cipher.Stream + // kyber.Group is only set if we have a combined Suite + kyber.Group +} + +// New implements the kyber.Encoding interface. +func (c *commonSuite) New(t reflect.Type) interface{} { + if c.Group == nil { + panic("cannot create Point from NewGroup - please use bn254.NewGroupG1") + } + switch t { + case tScalar: + return c.Scalar() + case tPoint: + return c.Point() + case tPointG1: + g1 := groupG1{} + return g1.Point() + case tPointG2: + g2 := groupG2{} + return g2.Point() + case tPointGT: + gt := groupGT{} + return gt.Point() + } + return nil +} + +// Read is the default implementation of kyber.Encoding interface Read. +func (c *commonSuite) Read(r io.Reader, objs ...interface{}) error { + return fixbuf.Read(r, c, objs...) +} + +// Write is the default implementation of kyber.Encoding interface Write. +func (c *commonSuite) Write(w io.Writer, objs ...interface{}) error { + return fixbuf.Write(w, objs) +} + +// Hash returns a newly instantiated keccak256 hash function. +func (c *commonSuite) Hash() hash.Hash { + return sha3.NewLegacyKeccak256() +} + +// XOF returns a newlly instantiated blake2xb XOF function. +func (c *commonSuite) XOF(seed []byte) kyber.XOF { + return blake2xb.New(seed) +} + +// RandomStream returns a cipher.Stream which corresponds to a key stream from +// crypto/rand. +func (c *commonSuite) RandomStream() cipher.Stream { + if c.s != nil { + return c.s + } + return random.New() +} + +// String returns a recognizable string that this is a combined suite. +func (c commonSuite) String() string { + if c.Group != nil { + return c.Group.String() + } + return "bn254" +} diff --git a/pairing/bn254/suite_test.go b/pairing/bn254/suite_test.go new file mode 100644 index 000000000..ea65ad2c1 --- /dev/null +++ b/pairing/bn254/suite_test.go @@ -0,0 +1,375 @@ +package bn254 + +import ( + "bytes" + "fmt" + "testing" + + gnark_bn "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/drand/kyber" + "github.com/drand/kyber/group/mod" + "github.com/drand/kyber/util/random" + "github.com/stretchr/testify/require" + "go.dedis.ch/protobuf" +) + +func TestScalarMarshal(t *testing.T) { + suite := NewSuite() + a := suite.G1().Scalar().Pick(random.New()) + b := suite.G1().Scalar() + am, err := a.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if err := b.UnmarshalBinary(am); err != nil { + t.Fatal(err) + } + if !a.Equal(b) { + t.Fatal("bn254: scalars not equal") + } +} + +func TestScalarOps(t *testing.T) { + suite := NewSuite() + a := suite.G1().Scalar().Pick(random.New()) + b := suite.G1().Scalar().Pick(random.New()) + c := suite.G1().Scalar().Pick(random.New()) + d := suite.G1().Scalar() + e := suite.G1().Scalar() + // check that (a+b)-c == (a-c)+b + d.Add(a, b) + d.Sub(d, c) + e.Sub(a, c) + e.Add(e, b) + require.True(t, d.Equal(e)) + // check that (a*b)*c^-1 == (a*c^-1)*b + d.One() + e.One() + d.Mul(a, b) + d.Div(d, c) + e.Div(a, c) + e.Mul(e, b) + require.True(t, d.Equal(e)) + // check that (a*b*c)^-1*(a*b*c) == 1 + d.One() + e.One() + d.Mul(a, b) + d.Mul(d, c) + d.Inv(d) + e.Mul(a, b) + e.Mul(e, c) + e.Mul(e, d) + require.True(t, e.Equal(suite.G1().Scalar().One())) +} + +func TestG1(t *testing.T) { + suite := NewSuite() + k := suite.G1().Scalar().Pick(random.New()) + pa := suite.G1().Point().Mul(k, nil) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + + _, _, g1Aff, _ := gnark_bn.Generators() + pb := g1Aff.ScalarMultiplicationBase(&k.(*mod.Int).V) + mb := pb.RawBytes() + + require.Equal(t, fmt.Sprintf("%x", ma), fmt.Sprintf("%x", mb)) +} + +func TestG1Marshal(t *testing.T) { + suite := NewSuite() + k := suite.G1().Scalar().Pick(random.New()) + pa := suite.G1().Point().Mul(k, nil) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + + pb := suite.G1().Point() + err = pb.UnmarshalBinary(ma) + require.Nil(t, err) + + mb, err := pb.MarshalBinary() + require.Nil(t, err) + + require.Equal(t, ma, mb) +} + +func TestG1Ops(t *testing.T) { + suite := NewSuite() + a := suite.G1().Point().Pick(random.New()) + b := suite.G1().Point().Pick(random.New()) + if a.Equal(b) { + t.Fatal("bn254.G1: generated 2 equivalent random points") + } + c := a.Clone() + a.Neg(a) + a.Neg(a) + if !a.Equal(c) { + t.Fatal("bn254.G1: neg failed") + } + a.Add(a, b) + a.Sub(a, b) + if !a.Equal(c) { + t.Fatal("bn254.G1: add sub failed") + } + a.Add(a, suite.G1().Point().Null()) + if !a.Equal(c) { + t.Fatal("bn254.G1: add with neutral element failed") + } +} + +func TestG2(t *testing.T) { + suite := NewSuite() + k := suite.G2().Scalar().Pick(random.New()) + require.Equal(t, "mod.int ", fmt.Sprintf("%s", k.(*mod.Int).MarshalID())) + pa := suite.G2().Point().Mul(k, nil) + require.Equal(t, "bn254.g2", fmt.Sprintf("%s", pa.(*pointG2).MarshalID())) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + + _, _, _, g2Aff := gnark_bn.Generators() + pb := g2Aff.ScalarMultiplication(&g2Aff, &k.(*mod.Int).V) + mb := pb.RawBytes() + + require.Equal(t, fmt.Sprintf("%x", ma), fmt.Sprintf("%x", mb)) +} + +func TestG2Marshal(t *testing.T) { + suite := NewSuite() + k := suite.G2().Scalar().Pick(random.New()) + pa := suite.G2().Point().Mul(k, nil) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + pb := suite.G2().Point() + err = pb.UnmarshalBinary(ma) + require.Nil(t, err) + mb, err := pb.MarshalBinary() + require.Nil(t, err) + require.Equal(t, ma, mb) +} + +func TestG2MarshalZero(t *testing.T) { + suite := NewSuite() + pa := suite.G2().Point() + ma, err := pa.MarshalBinary() + require.Nil(t, err) + pb := suite.G2().Point() + err = pb.UnmarshalBinary(ma) + require.Nil(t, err) + mb, err := pb.MarshalBinary() + require.Nil(t, err) + require.Equal(t, ma, mb) +} + +func TestG2Ops(t *testing.T) { + suite := NewSuite() + a := suite.G2().Point().Pick(random.New()) + b := suite.G2().Point().Pick(random.New()) + c := a.Clone() + a.Neg(a) + a.Neg(a) + if !a.Equal(c) { + t.Fatal("bn254.G2: neg failed") + } + a.Add(a, b) + a.Sub(a, b) + if !a.Equal(c) { + t.Fatal("bn254.G2: add sub failed") + } + a.Add(a, suite.G2().Point().Null()) + if !a.Equal(c) { + t.Fatal("bn254.G2: add with neutral element failed") + } +} + +func TestGT(t *testing.T) { + suite := NewSuite() + k := suite.GT().Scalar().Pick(random.New()) + pa := suite.GT().Point().Mul(k, nil) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + mx, err := suite.GT().Point().Base().MarshalBinary() + require.Nil(t, err) + var pb gnark_bn.E12 + uerr := pb.Unmarshal(mx) + if uerr != nil { + t.Fatal("unmarshal not ok") + } + pb.Exp(pb, &k.(*mod.Int).V) // Scalar multiplication + mb := pb.Marshal() + require.Equal(t, ma, mb) +} + +func TestGTMarshal(t *testing.T) { + suite := NewSuite() + k := suite.GT().Scalar().Pick(random.New()) + pa := suite.GT().Point().Mul(k, nil) + ma, err := pa.MarshalBinary() + require.Nil(t, err) + pb := suite.GT().Point() + err = pb.UnmarshalBinary(ma) + require.Nil(t, err) + mb, err := pb.MarshalBinary() + require.Nil(t, err) + require.Equal(t, ma, mb) +} + +func TestGTOps(t *testing.T) { + suite := NewSuite() + a := suite.GT().Point().Pick(random.New()) + b := suite.GT().Point().Pick(random.New()) + c := a.Clone() + a.Neg(a) + a.Neg(a) + if !a.Equal(c) { + t.Fatal("bn254.GT: neg failed") + } + a.Add(a, b) + a.Sub(a, b) + if !a.Equal(c) { + t.Fatal("bn254.GT: add sub failed") + } + a.Add(a, suite.GT().Point().Null()) + if !a.Equal(c) { + t.Fatal("bn254.GT: add with neutral element failed") + } +} + +func TestBilinearity(t *testing.T) { + suite := NewSuite() + a := suite.G1().Scalar().Pick(random.New()) + pa := suite.G1().Point().Mul(a, nil) + b := suite.G2().Scalar().Pick(random.New()) + pb := suite.G2().Point().Mul(b, nil) + pc := suite.Pair(pa, pb) + pd := suite.Pair(suite.G1().Point().Base(), suite.G2().Point().Base()) + pd = suite.GT().Point().Mul(a, pd) + pd = suite.GT().Point().Mul(b, pd) + require.Equal(t, pc, pd) +} + +func TestTripartiteDiffieHellman(t *testing.T) { + suite := NewSuite() + a := suite.G1().Scalar().Pick(random.New()) + b := suite.G1().Scalar().Pick(random.New()) + c := suite.G1().Scalar().Pick(random.New()) + pa, pb, pc := suite.G1().Point().Mul(a, nil), suite.G1().Point().Mul(b, nil), suite.G1().Point().Mul(c, nil) + qa, qb, qc := suite.G2().Point().Mul(a, nil), suite.G2().Point().Mul(b, nil), suite.G2().Point().Mul(c, nil) + k1 := suite.Pair(pb, qc) + k1 = suite.GT().Point().Mul(a, k1) + k2 := suite.Pair(pc, qa) + k2 = suite.GT().Point().Mul(b, k2) + k3 := suite.Pair(pa, qb) + k3 = suite.GT().Point().Mul(c, k3) + require.Equal(t, k1, k2) + require.Equal(t, k2, k3) +} + +func TestCombined(t *testing.T) { + // Making sure we can do some basic arithmetic with the suites without having + // to extract the suite using .G1(), .G2(), .GT() + basicPointTest(t, NewSuiteG1()) + basicPointTest(t, NewSuiteG2()) + basicPointTest(t, NewSuiteGT()) +} + +func basicPointTest(t *testing.T, s *Suite) { + a := s.Scalar().Pick(random.New()) + pa := s.Point().Mul(a, nil) + + b := s.Scalar().Add(a, s.Scalar().One()) + pb1 := s.Point().Mul(b, nil) + pb2 := s.Point().Add(pa, s.Point().Base()) + require.True(t, pb1.Equal(pb2)) + + aBuf, err := a.MarshalBinary() + require.Nil(t, err) + aCopy := s.Scalar() + err = aCopy.UnmarshalBinary(aBuf) + require.Nil(t, err) + require.True(t, a.Equal(aCopy)) + + paBuf, err := pa.MarshalBinary() + require.Nil(t, err) + paCopy := s.Point() + err = paCopy.UnmarshalBinary(paBuf) + require.Nil(t, err) + require.True(t, pa.Equal(paCopy)) +} + +// Test that the suite.Read works correctly for suites with a defined `Point()`. +func TestSuiteRead(t *testing.T) { + s := NewSuite() + tsr(t, NewSuiteG1(), s.G1().Point().Base()) + tsr(t, NewSuiteG2(), s.G2().Point().Base()) + tsr(t, NewSuiteGT(), s.GT().Point().Base()) +} + +// Test that the suite.Read fails for undefined `Point()` +func TestSuiteReadFail(t *testing.T) { + defer func() { + require.NotNil(t, recover()) + }() + s := NewSuite() + tsr(t, s, s.G1().Point().Base()) +} + +func tsr(t *testing.T, s *Suite, pOrig kyber.Point) { + var pBuf bytes.Buffer + err := s.Write(&pBuf, pOrig) + require.Nil(t, err) + + var pCopy kyber.Point + err = s.Read(&pBuf, &pCopy) + require.Nil(t, err) + require.True(t, pCopy.Equal(pOrig)) +} + +type tsrPoint struct { + P kyber.Point +} + +func TestSuiteProtobuf(t *testing.T) { + //bn := suites.MustFind("bn254.adapter") + bn1 := NewSuiteG1() + bn2 := NewSuiteG2() + bnT := NewSuiteGT() + + protobuf.RegisterInterface(func() interface{} { return bn1.Point() }) + protobuf.RegisterInterface(func() interface{} { return bn1.Scalar() }) + protobuf.RegisterInterface(func() interface{} { return bn2.Point() }) + protobuf.RegisterInterface(func() interface{} { return bn2.Scalar() }) + protobuf.RegisterInterface(func() interface{} { return bnT.Point() }) + protobuf.RegisterInterface(func() interface{} { return bnT.Scalar() }) + + testTsr(t, NewSuiteG1()) + testTsr(t, NewSuiteG2()) + testTsr(t, NewSuiteGT()) +} + +func testTsr(t *testing.T, s *Suite) { + p := s.Point().Base() + tp := tsrPoint{P: p} + tpBuf, err := protobuf.Encode(&tp) + require.NoError(t, err) + + tpCopy := tsrPoint{} + err = protobuf.Decode(tpBuf, &tpCopy) + require.NoError(t, err) + require.True(t, tpCopy.P.Equal(tp.P)) +} + +func Test_g2_2add_oncurve_issue400(t *testing.T) { + s := NewSuiteG2() + p := s.Point().Base() + p.Add(p, p) + + if !p.(*pointG2).g.IsOnCurve() { + t.Error("not on curve") + } + + ma, err := p.MarshalBinary() + require.NoError(t, err) + + err = p.UnmarshalBinary(ma) + require.NoError(t, err) +} diff --git a/pairing/bn254/test_vectors.go b/pairing/bn254/test_vectors.go new file mode 100644 index 000000000..8db728deb --- /dev/null +++ b/pairing/bn254/test_vectors.go @@ -0,0 +1,5517 @@ +package bn254 + +// Generated from bls-bn254 tests +// DST: "BLS_SIG_BN254G1_XMD:KECCAK-256_SSWU_RO_NUL_" +var hashToFieldTestVectors = []struct { + Msg string + RefX string + RefY string +}{{ + Msg: "1480fe746a4af50b1aca584ef653e53e96ce83f59775e301375e61523d2fcbd03665778b7418f545806ddae481b6a75f93e64482679dbcd2896a4df954c1280efd625b9950e9c6417b8598d710d80d3c8b83c30e13a9195ad146b9d2c4add9bb5f925375464e380ad4557271cc5be58cf07a0a1c365e9c0d8ceeec9d14fd960e7956a02b724b42a3e7da832608603e34c0e795a503876cfabe3598d04403b30de08f24bc405158df7dd7884b89bace0abf1fa46d06ac80aec1", + RefX: "284ca89d3e7f530c3ae8a0b71c792303729d310e6d2684b932752deaa31ad201", + RefY: "109c30ccb21900ca2920bc8ecb49ae81e82fd76c6255a494293d958039fbfe5c", +}, + { + Msg: "e8db68fa4d80aa0522e51d8bc1a9b59d4e309595a171b60fbc106f64330b2d304bed3f9a622557cf12219f9842be6713730a4c43b1744ba9406a79e149dcb64b3c929508540577bca95c389618e71dd11ef8a3612a571a85d0176d61bfed6bd37c9d92b70313a0fea82361a59cb931029bb7da59169ac22c51d431fe5c5c77", + RefX: "17a163e5353c5308d62748769cc92016f4954e203ec57104b0634ee73be7eb2b", + RefY: "20ad798cdd596a25d0ce1e934ba3f9a313f1da05cce14c3d8831650782e78cfa", + }, + { + Msg: "f120ccff1efc9668f53ae4875d10bdfa48057352ee49b9c1c1bc7e5ef16da252d9bd6b18bd77db70b0768b4138ca3e8634b8a927817e64137875549ad430374cca0790eccdbaf1ac270b2f567ff406d11eef7addf269cdb79337a5ebad51bce41db42c08a1b4621cf117a0f0f96b4a125d261015e4e54ce52fa9080257200d0c177b316ac6bf3cee02a895b29cd4d6ceac6c324a0921e359aa231bb5b510d9", + RefX: "0fd89517be4e7318a3a7b1cb0453da812aa0e61b36d4a5bcda8c58a107a29bf8", + RefY: "031399e6c92631c02947a82f37cda2a40594a2d9a651a4a1f532736f7ff94606", + }, + { + Msg: "ddfb30fd059c808b66a566de572e87cad2310eff44de9870c882ccf1f043eab0d0f7e74da1631e21bb62914a42bb8dd6b1cd4aaa1cd028fed0e0efbaf0a844c3fee4276c94451710c15fc3a02cd3efe049eea07c2085746356b3968c9be6ea51f303d80934dc0856f2786bd6178860ab482ea21fcf7ade1368bb45e844b6af6913dc4676c876626f35", + RefX: "2c0183c47260a33595cee027c483a8cbe65f7dfb61f1c96c92595628db2eeb34", + RefY: "1bcbccee20b78da4702879e45956f422646044a57d79290c285b6144567aa101", + }, + { + Msg: "a7131973dfdf68934facde7641adba11d52495ecd88063f9ea29a272765438ddf5816bc87e88d2761f7710572923af0b795d08da17faa805818279944c477cbd665296d938fef5f127efccb1d6099793d54b02c419c29a0d84c08d541d299acaf162cba29ccfbad9f29aaab222a2100967e3a99477f3b0eef9229c01335d08cdb34a55f9ec0d465348a3eed67edcc9bf425b5faed33463b478bedcc9604a546ca15b64e5", + RefX: "1cc575de96469044cf3c2102fdfeec29f272cd75136554b8b118fed095f6c25d", + RefY: "2aa349db0ba3c4bec67e2a420e7564285d561a7e4448e0ffabc3bc4b97430147", + }, + { + Msg: "9cfb788fc78bbf2c507ebc9ee4c700926ea8703230af62050a3e95eba87f5946c499f9016cb50f7488c1ed33b249cf6c5d801ff16ec8eb72a7dd5d9486c9d1ddebfea8359aad862fb5b885d389c15e7a7cd77ed8ba86c31bb1451db46c7bfbb8ae4bbf4632611905d95c7ac7850c4215684e994f9dce883443433c77b6b1b08b1ebacb9649e7f7042a5198be7c1715f22372e0d9825ea28d451489420f3cadc3fe09f9c958adae479176327ff78c2404885850c747c7d94958255c61cf6a7f90a879", + RefX: "0e127ea888e5df1ae3179f143845c035cc461e18c94e3dfa8906ab707d19defe", + RefY: "230721aff0f0b3ee8707ed8aef8129b9283264227c0075daa738c86e4d1f7b11", + }, + { + Msg: "d9918cdd75e834a045777c86737fba0bbaa928", + RefX: "27666b8e122fbf108c56e6323fa27029898ee683608404c4bd03929151c426ed", + RefY: "239f664c3e6be837efac80ee5d542eae585a209f86f95617061ad3306bbb47d1", + }, + { + Msg: "7e243f4a51f7d759bc7a677c8dec7a7b8dcc1d78947f4fc7c8ebd12607a168802061389bb6ba52ed69b589bd0225dad0d5137d1a98f8a79c9854171ea1d6be3ae8fa58152af6381eef529adb5d98b8268151f49a3942c4e13b4445c7d54d63c058c0097fc95c5ef7d6d3713289d6e54ba272c3c50890e575b2ee1fc2be3d28da1b4ccc969500093e7130d2010b592d3c97a1160e583c83565d8266a1221726c8669e0aaedf", + RefX: "2f0ab9fa482007bf95590624b4852b849dc7b1b067bbb699688f7ea4678c2871", + RefY: "0c4687097926f0b77cd6d45c2ec5309ec444203110c41923db34a198daac75ef", + }, + { + Msg: "3d661d4bf1a886d7d484290f4a5c6b6e9849880ffec2ac1c0a06bdd4fb9a2e55bb601d3d1b0ce71ff95feb7b83f8a92abcc8db60498309dedba2aca85e211872bd32d878a47a6d82210cefa683672c1be0734316255c3da6277ede52099f7d", + RefX: "12b29d062cb561b271b1ff0d868d4bd95ebbe4b3214edd4276aa61be61585511", + RefY: "2fecb96d9884ebd21822de27590b0c3b9ceecec33cabc66d3354eb0e1b8df117", + }, + { + Msg: "846e0c0fadb98f96874a91c51e5001869a46a8ce99a8a918ee73f0b22bde5b764f34da8fc9572e", + RefX: "008d67fdfc87411c3bb1ff97a7bf1cb5212026409187b2fee5052c86b08d726f", + RefY: "17c666b18def6fdb1e6e68c81f42de839a02beb6b5029df6b06e909632d055b4", + }, + { + Msg: "9c05280845663f38baf7dc0f806ca84c8024e77ca5885beab5f946be2bdeb0cab8f5e236952df4b2d4104de2d26c90b620c1d176b76794c433ccaa5dd9b8907c11caab9e82689757096e31f8b22db0f9083e2326062601e05d5d7f22c31032d979596f639d94d0dd8cda2dd56589a4216afadf872c0cabd7ff14d561f662be02edd2f8f7c0a769b0d775bf", + RefX: "21eb7da44502e7e408f453ffbd2e3c14e0b1dc93e79614b88099c658de109edd", + RefY: "2e5081d5d0d14e329ae014e910cb77e6434866ea8cb8887577f82620b2a0ee6e", + }, + { + Msg: "9169a33c2bb98d341b66bd3bdf7576a212f194c053c651e6524e6841d27b123c4fd363757fcb5c1241", + RefX: "06f9b95aa1fb7b6f928f4beb58ffe5ed4b0fb741003d04618c6bdd6333a5688a", + RefY: "2a14e4d397be562553252fbb9fb1000627e3da2d936dec8c493326b8653859c5", + }, + { + Msg: "75df82d44775ad6a82ed7273d15720d621deae1c6ae1449546eb64fb5bb0b56c1b3eba55adaaeaae87aba98c838b5f3ad677219e56a60db41bdc3562537bcdbdf5085745211043951f903514ac3775de1685221be7de7029c76abc79210d7e0a04af50e6a09f0e14064a1d9c5a9ba3ac4bc41a3853b2673ad5ba903c4aadad0f6c9d58d328bf94ab73ee7350451d34faeb608750", + RefX: "0f5d7b63b0002c8a30eb02283e4682eabeaa5d3cc216f8d5d27dd95cfbdb14a3", + RefY: "2ca2c143a8913d8d67c39158fa4ec259db5a35dcfeb43ab1076b362e443f8e97", + }, + { + Msg: "6a4b62857719d8a6a4e803221d916d3d9a52e7a56af5f9d2b2ee387f7b7f139f", + RefX: "22f3f2c67333c4d41803ce1a07346da245c1396fc21a9eaba8fa5e372c15cc2e", + RefY: "20cb585f4724ea6f7bb5bda4286d6d566afae3c01009adca99546b9230ca4f8f", + }, + { + Msg: "ebcbbd14ac4118ed6978aa52a7806b1588d327d30a4031f4981460c073d71d87e1a54e043d76cd48cea6537e0bd099f1a60dd5bf0ed18124b22829213d4a57ad18b7159c8cfa6ec37961", + RefX: "0890ca383da0a6788e953387736b1c8dffe0d5fc53d44d48ea49755fd3cfc7f2", + RefY: "185f91f207aa1b0d21ab663165229741f99379a7698175adc2e6a85af883f77d", + }, + { + Msg: "dbcf4ee199177a54dd42d250cd36d761b353f224647c0ca36c67b421e99fc55ccc05af05a29c2852b9ae62e7f5f3548ffa909c4fc09419a7e3bca54878af095191f827f6485a213d137d695128292ed3cebfc7899068c4a6f823ef7056e833f1672b8011bb9bedbf5c27bdc08987d94a3f", + RefX: "133d997dfb6e052fa9d08f05d0e50910d1a7a230f1471597e9805499ed0f0806", + RefY: "1175a9d6a084cc4508c0ab4a17891396f34968119dc2724bf58935b3ce0eca90", + }, + { + Msg: "63482b522285a2cf682a316433e0b660581db457d358f63c8c216f151180ce8f6f50784d4661268936fc1a66fc27aeb11b87df10a8f13133b71a613486de2ac4d45795f7c6d4860e75123b0f063931eca4438431e446e98255eb97444d30cd651612b930876329ce702e9434347aa8de04d80627d3", + RefX: "17d3aea1cb3552b56fcb67250e89e582fd7c6215ca654846632762209cf28711", + RefY: "1674f46dfe587b8a29114b01a8194a5bb55cfe2b97bd10370b26fc35f78de675", + }, + { + Msg: "15f0eb3a58af5fb0cb2aaaa437c72ddd7560cff2afdc5a85ff83dc9ad2244053a9698966b77a26", + RefX: "0957a3bc2a039266087d30d2cbe1a109783d02197caf2618edbbde832d3e6224", + RefY: "01f47ef73486ca5e5280ddcb444e37dc01f45b0c8defed4c4c589db8219bdb66", + }, + { + Msg: "0f3a257a84be8e28185e3563de6781ff164548cf5bfc5ed47bf623d6bbc6c256cf8845f3f115921d1268ed3c1712c587e895", + RefX: "0ec8d571cc6a070005bd13aa694cdf241c8295e4fbe0db5842fd2166bed04138", + RefY: "0b705559df24c6659ec14125714d8289728c81d8fec90da482f4df04da43746b", + }, + { + Msg: "5d0f13bef54a2a0343fb1f0d3fe0d8c429830dcf48922e2ca6923d005505c78fd369010503cbd5d20248615fcc49b2581d880f9b05af2f8f3572515202344385480a8aae94dc830ccca0783744d322c1c438ab16239d", + RefX: "162c4d8bdb39bd4dc7bf61f3cff8de0043123feadd88d86a797754d1393645a7", + RefY: "239df821ca7ab98102a30a0cdb796e14600c01b8b409bdf6a60e45223e1faafb", + }, + { + Msg: "64b869af76f22877efa7b9d75aac0337ba81457c4800d10262244fb792dd792f186b4561b0bc8e4cf77513bd2c1264ee714077fa4026ca37ab67af1b892cdccae9117b9b0c42cf8ffa4f6faf64d856574b06f73dd6fef8228666729dca52540be3267844dbf19ce1122d36a661e305edac774e6d596c07696cd02235d914995e380fe4a0d02cfde3cae4378a17aaebcd14d78e73c9c80ddc47a15ec197784419c4d255e7c1c0be74e98f35fd81e129d463b2fa64fb3cca6946dd3a11", + RefX: "1c5cd2d3b7c606db8f03be3392eb0900e763944f56643a6a38f4f76c7dcec05e", + RefY: "2f0d14da35eae1f352e70cf2b4d0c0080e36bc4c72584293666ecc913fd60f6c", + }, + { + Msg: "651681354af73a258767754d92c4a4c7be92815cb5a5b3e463aaf0ae4d8ab4eeb37e395b952e10ad50d9741d8b48361693975688e2543ffc60cbd2fdcfc9bac3b6cc5d4c9df367986266ca03c997bdf81316e8d70a9a856583ae11393872ce89c507da99fd45331bf1d1195666162bba0861e4037d81ce28b1b70b9cba5066dc28dcd30fc86a6bd2aac91c72b559784a348933e385db0b2eb931", + RefX: "2f5fa35dd2b837293d0b65fc713a105dd75b43a1afba6b19ebf6469294b63037", + RefY: "09b15a19b30385aa57e53f89f78a3f817b36b6c010df35e4fe1fba7904da92fa", + }, + { + Msg: "565a9a8cd9a746ab3ab20f8227e3e1b49d07e9735203eea880a9970df302138c9796eb3e39328154efc6b51df64c492d0b3b2d6f571d0cea3e431a88a66fb861440dd60581cb3dd3307ba2ca34d3ce88a11b6db78f671cbe", + RefX: "1878a4f2c9af5119fca580651526847fe58ada9242937c2b75b7d85767be1c1d", + RefY: "05d5d8a6e5ad37d3319a9d7545321eab62ca1d7795f3390946057566cdc213a7", + }, + { + Msg: "3bb8ec17177f5081ffbbce064b689639b39924b51586f0d0c088eedb71d0ed3f", + RefX: "26946a0bdd65a8dac59e7dc4b2b16d603dbc7e42f6cf98c6930abebf8bdf25df", + RefY: "0300687d365ade65ec7f579f8131e1a50c9406f9a5b40935dfa2c640edacf70b", + }, + { + Msg: "4fcb02a47a8a0558ec6d5da04788349c78fd72cf3bdc21376b5b2f9c8451f130c334bd3b0df5111b37e8b5408901b98e835a8926e2f7a9626cc0c05eb582b2bb84528a80e1f72d8c42004f0080c24bd756d14dcd0c0abc867d279105e7006a6fc1831c26f1d172ed16fc552dc771057fe8c2f82960bf63b4c1d1c87e97b1d504d5582eb300a9e40c2034ab8a204f338649c351f9d3664c915770e49a2759", + RefX: "147c82b8a0e51907147040ec923859b5d1c8ec0e06078e4d4a3daeee341398db", + RefY: "2a36ed8abe9e91234129a2d90310b46d56478909fd77fdc6f23e9c820e39f283", + }, + { + Msg: "49f2ce09ebd763346b36597913e530aafdb8b52a6aedba807c5dc1ef8ef2e8f641e4a75c404f48635e2a58970c7b827f64b7038a54213538dc79af58fe8d9f81dea3b1a2b02730a5b480617c3fbde1b42981828699476cff186a6e90defc1cd5c4639b5c331711b5f87d", + RefX: "006239d9956e64ee2cb349ce0d9311e6e5b1935a7789c106172e8c615363f892", + RefY: "18d184a0ad41de839d1149943bed1e7e099a919af712a895e727e972b22a75bf", + }, + { + Msg: "f340a6f6bf72b1dfe2f5ddc22030674605bd8f3621a0a3663c80e4c80cdba195ed9b5403c0e504268a21be9707aa5b1f60ae90b467374961c31c13af5e4db042a3440b3742e3d6c6c8abc4ca8bbd2e4bc23ee7b758d9d0a03573982a1ff3f904e8694a5097cee9ad84753a2e51d8428f0d7d36cd5d48aa5cfcc0164ad7015220f75c82fd29e12a", + RefX: "201f0dabfc61935a467a201ab6904e0601ec08c20832afcc07d0c460ab09a050", + RefY: "036ea23c96e2cab1b7c5bdf0d335ba0e0a400911990474b3cebb8d9d4f721dbc", + }, + { + Msg: "2a34f061fb84e8f09a7458cc05d8e25f03423c3f94963176f7dadb4ffd333c4cbd9e944fd6b67e4f7492d067d381fdafaa9facfdb9709365e0fb863e9d0d488abb86a9d8a678855e5159f23d22549051e4da1fa1d810c9786e52779ac2fc6e275d36d8b5a520e3a3a38cabb7e4eed9a350c2352f61217ea8fbf688e0cdd532f788a0e1d448994f84bc1238de101e011eef0ecced34783eba82a0", + RefX: "1e74bb21b96a56a0d13f38ebdccee57e166d91585eb6ba9deaf6c48bf732bce1", + RefY: "1ca2af3e606ec5dfd9413b290d37614dd6bb72fe7392245d89e02482df002678", + }, + { + Msg: "438f49a1d5c4e19b2d5a5ea4b9ef3a2d02bafac45cf11f3b6db70db1550238c63bba05a208beeed216fb8884010e348cbc3857a31562de92708615a231cbca444041e52dc3a34dd918df10e453791f66bd96a7002f9833a4c5e0176370cb1ba52a131309c1b22580b50fd14c21f05668b7275f54cc1feda08d74115574936a194df789bbe0ef2324", + RefX: "17c040fb1cad9844123a5a3190b3f6cb5d55744e253ccc2317b977543f4795fb", + RefY: "03db4fb699deafb8747f5a3b65174b5db70acc679748956be960dbb35a270784", + }, + { + Msg: "3c673dc270bc38f46b3de68321d4141bcb25076ae7c818883c49bebc10c03b7f470fa947c370a86d6a380fe1a380af4b19f786d79782e833f4534eab7fd295f59a95cfdd868e4ad6d6b0040e726e37c5a77abeccfa55419229f6d3422d3f74ab7023e91aea18b110dbf81f4fb3a9083fe6707dd200598e2b0fe72a0daf740fb7a9be197c7c6dd8b570e603ab6841f01b20d4ef2ae16f58c2d777bb0b6daa8f700c3a9c54ba7ff45549309abf8d64d934a956f27ddd736701d40966dbf9", + RefX: "05a6431789de47a5683d365546a1695f619762dc7144190d22a9d897f0321e60", + RefY: "2be4c163c12069505e87dc94846c909411b4b3e997c7188c19bc73b0fb1367f6", + }, + { + Msg: "bc67ce3be221dcb83bd5419bd87ac7ada3200ed8148d51775b5cde9bf1b06ed6a5ea58a8b62e6f018c6fe351b3afdc165bcde26fb28f4ee868fd476816", + RefX: "0a0ac7c7b5ef370090b6ad5f8bfde477e314c72a81b30dac35792530b1cfb6cd", + RefY: "1d8acb96c04a2119b4dccfd5affd3638d0b92c59ed163ac194b9d1436ec62431", + }, + { + Msg: "f6d0f1ac43b52259e41ff16f793b0766b82afaa79896e268fdd73c553ffd4ffd7d3f1f9126bf2e0071a9b2f6d92bcea05a468f1fc241e142074a71d47253eda58e773c505830608f69ed77b44efc5bf4bf811e68231454b8bc1a07566b50a9f57b3d72ac56e3b44c47f1d74c0b0fd0e4db900419b8", + RefX: "1eb366d4c6c83375daf9803252f9abb19164d7e5a711d13e8855fd5613bd7cd5", + RefY: "299fee2764bbea7b97cc227b89d1957b81b9242bef89c55626df15552b51f9d9", + }, + { + Msg: "be2f6043bb935cb248aa47ebe75ca01dca409b4093db94e64b59da7f0877e57c23a83fa0fb37fdfd3e2afebb1c521b170e5c", + RefX: "281fa0dd6338d83c5b8e82942bb6ae821170b5a3ce2e2c9c5b4cfc1771ed1e00", + RefY: "1b47bc7a2dd2c3ed162f917cb8cac84bc23342dcb0f89b4e2111d1e81a71b267", + }, + { + Msg: "79baaabc33d83e08654fe2bb68a1b98986206f72a154737338bf171e0840a08d5139ede88e9110f2dc6f06e7f8f87a490a0488dc7271837f28594b6a4a3024a653a04e8259197f427d78cf7371926149af2432b67b47f9006a0682935b2d8fe346114fdfbd7f3d8975c474f3fe25726f9ee6793bc4acf3052003d60a8c3c4970ad024f82", + RefX: "1168a2723769917177356e8817cc9aae581431a364ce8a03888186fc87358c8d", + RefY: "0db40dccae31b818762d21afe7f6efbb297a3d0d3c4050781b7a96826d4de9d1", + }, + { + Msg: "a1bb84190ae86359f75515885cfdeb040e82c49eb43daa19ed515ed800b58857ddbea6e901c4ae7254651c94c59eaca61776199345e9f6a32b9b894faf7d0d5956c11ae2ad331a0fa74a169206b7631024f57215e6bb24291adde792b36ce2f0969d6cd72fd6aaa8c84397adf90b112c7222dad982bc359fabf3b389029e334d9d3edb4cf761dabb13cf20387cc7ac8f5776bef5bf9237a738742f0749940bc66570b2", + RefX: "1e6a9234bd2954a08167fe2c88e5ece1e24cb9fafdceb6ebb1652a5bb5fec0dc", + RefY: "0c6a64d4d48e1cb2cd32f5db5a85f77947441ce9cdee5cb3d16b747b28ce3fa0", + }, + { + Msg: "ffd182591cae3bd5f2bb4fcb6b3a9527f997add0cf63e557ebed85168436a5802196ce93855aa87b62dc70513fb3119cf7dca1542974caead7cd8426a61fb3c95de37f07f541dbbd1e498c7d9552dfcd2ab6f3d5c2c67615bd93c98fd42726feed7806d5d6", + RefX: "0484698b99e29933ae7cb12230aa7b9f1487147b3e8ddd0bbdad89cf20eee818", + RefY: "028d580b8b947350767c0b463f1176889c65d5b208aa78780652582056cf62e0", + }, + { + Msg: "df6d0ba1ec1b6aef2fd31ab54e18ae912c7e96da8898ee0a97ddff51b54a99af7b779e42b378ec44d7a06d03f8bd0763df500e3d0686e26eec65fa7364318bb5e42f17ae71ba16284d3599e2b60a78cc49fa7e4c3ae256dde516caf18a910e901be9fad1fd5e9ecdd52fd894e70b1ad328d5ffa351e1989e33a497ef6869ab0f074017678373e4fdf2ecb188038bc101b182bb8ff14419a74f658f79f7329dec1c38c2d8ebbd128139985d0fcaa0cc7208846342d53fbea45f95022f58f418ed71306aa9a33c8669b1ff7e41", + RefX: "0a9c04ba31b2c353b4f8c54d52b91957fd4a650d46dc26f8324f7acd8cf9e22e", + RefY: "121388176a89caba564288641a40c9abb1fc6a2c0d297206feee8e582418ec6b", + }, + { + Msg: "b561bbfe5c493ad0a679b25566db034383efa9098ff26ee40b0da2abc1dc5e1b66691fffb9b23fda2254f4f9fb282d3a9dc919f4bfd265db39d4d8395d862540acced032081356ed19e28f3f31110a60267d3009f73fa98d1a91a59dc9002850c0d4262726fa8e193fbc20e322bda78e85e6495f7c1d25eb1eb6af7c7d95a67b38d72d9c6bc816eb33984a17a5994e73f0f49c3ba853", + RefX: "256a26f2341e7d78612879ec5788880171f138d3f2ecba4e2124a2c990b91e15", + RefY: "2d377d54487546927a17c2a3e14749672d0a37e6e138960f2f2e69c342f3b7ed", + }, + { + Msg: "a41d4bd925e55346b9a2e4297cc12810188382b61450834c9974961ffecdb591c0bbb05bbf3de6ebba0d5745b490e1f599ad8189aa523a18ab6a28f573907df46075cdca2eb0e2a410810d6ee5dfcde3d4e0a17af2fd13f327b6bfab7fb119de776588b438db0654667c3866f5582851caba01e8f0e57e40d36115b84fc68c975163506cc2", + RefX: "0758b68ce56622f870b656417ea757ae17152efbcd342829ad2fdab13b3333ea", + RefY: "1805cca543d1597ab86a4705bbc3059c7df5ac1c93bf20a8fa8c9c5e72c65476", + }, + { + Msg: "7f2c690ea84fa673e02c2ddb4e69cec34d2c9a78ed5239a6378b0068f165c3c00f0865b6fdd685ba241f0bee4e5e9e733f9e644cb4fd35efbaa2a660bcb7d7408c04a84e6bd1656698e906e5616bce7aa203b8ca0d6872987eaa0236e3b4b3fc5fb78af13f5d6c9d137d57967bbfb676638b907a81ec9b7dbcf03ed62058284b9a4797956e521a429a8b2ec3d7f8c06de34c0973f059bfd3b4ae34a2509369e77487d80debb0162926b02eb5ac3d2be6a59fbe80d5890150eaedf522b24e4a5675abad3a6ee2", + RefX: "2c47fb6bdbbf97e315b63db6152f49a6ebf4ce1d531c1dd7327038aac95ae261", + RefY: "26fb75b86dee77fd6497bf82e0d0ac3b2a3a87140b57c98006603b68577edd6e", + }, + { + Msg: "5d5ece3c92e189546505c767fc2debbea05872dee1e8f6ff2647b6d08abb55438250b8", + RefX: "117333aae7be9b534673648fefac8386c0cc94d272cc93268f4a933363693410", + RefY: "1f52af16d31e1a65c73363425199a1c3904024acfa996fae08b8d57f5cc5d8e3", + }, + { + Msg: "7649eb831764e59b14b17acb775689b77cc5b411676fad16079bbb97306f05153bcf06c6d34eb7ed6612192f9705446afc663216e77150b0d05c180701c82e5c811ff1a34b698aa8ff19c51f2784", + RefX: "15a2ce69b07591a1679d6862307e7e1d0cda51fc6fdb979bbd800e795f1e5807", + RefY: "1041e4f27fbba68139f09a7c4e7446710e6ec48e16d5476e25e680c1e1411427", + }, + { + Msg: "6aedcad5904be3ab64863ae5646ff384d80f3ac39f", + RefX: "0af03206e5a6fab576202fe5ab75d6f0f4be9afe9b761898b64bf6e64b118cc9", + RefY: "193105354c4cd87353c1140a2b7016d16e9df1f165cf6b0b6f45c5768e36919d", + }, + { + Msg: "9c4ebea441e61374d2d10f7d5d6cc42881390469349a72a59e242fd979e11622eb3fba96349b439889d1b614be78d10e85c299d5c7f64af24ebd3aded5c576f4940b36cccc57ed252cc6cb74cb765d2ef65e682f2ca8", + RefX: "1f0f55f0cd414608771da541ef7a1f73cf0a24d8edeea2aed0d31e6e0f38c5f3", + RefY: "1bebf6f7ae56300421f423597556a62650de558e16d800958d9778413bf77de8", + }, + { + Msg: "453e0de3554b7e63fac86f13b4c32b85292ce530b36dbb6bacf7b54a94b6af48da69966af64d2a2a117656242c7d1116ddc0", + RefX: "068a81842f15f470ab65868c958444ba0274e1d8fb453a9de6c8b35abc72d1a3", + RefY: "1a4bfdae321696d3bd95e8f70e7754b78ff81f741d502a8668245101c61e8b52", + }, + { + Msg: "1bf1aac204dd773142ed46e1db2781e84d75cdbf24dba3fe8638435a73abd710554127be592f9f59f8651e0180fe1b7a4d55f62c38f25884bc3ac77f5a4bb3f284bdafe6a14fe8d06344886c52355e5dd0799454491977d41ac2990a79667bb8f07c6f5e755b7c6ff54a4b80", + RefX: "14f7eb52c93e8a59864f661353d5172c43d519bddc7c5abe2ff93bae3eec6695", + RefY: "29a9183055b12341de00dc7b21e1328207aec105acf0a712bca8b97cdc498b24", + }, + { + Msg: "024fc44ed9316edaad9f0afc7d7eaaab6ac186889e71eb226e2ed90387008df31385529308dc1d652861f040407c43157958feab94fcf2c18948041a5d08a30ed9ca8f76741684abfff1cfc9529cf14815ed18c35ac1320d187c826f01576955d11070b3b271e39be858789e867d78c74afdeca3ab7aa7704ab789bb4f344f99a79117ff0566bdf59dbbea5fdb01cead5e0dc30508b9ad4c4b9e350adc773ef89c", + RefX: "142ad33bef594375670ff19a8f4d3d0fb81cbfbde5407054297b67a146a6976d", + RefY: "14045212447e41e112fb0ea88ebe9abd333f958639596db72eb4e28b799c52ba", + }, + { + Msg: "c1744aaffb3e153c118d97caae331b147ba20e29394b522f8d4f9297585f806dc611d0fbb7ad9254d7dfae140d9dc0c5dac95028342295ffb672327c6fb29c56b92359ef439f34476ce9bb80145b523bc00ceb1f8f81d59dbc6932594466292404dfa0a7eaea60e084cdd409c7a0fedda58ab39c4bd1f69f01e46f9d9aa091babd2f368a5de48401b28cb0b4ba7058f3f8a36b17a353d3e0741ad04b3841b415bcb055781a61424df06baa34e404361b5498", + RefX: "06e6dfdbcd9591de3ded99a5030d4e17081edcd15d94cebccb0bbfc6556411b6", + RefY: "222c0036181deef73b90a200493f27c23ae3ce673650f616fbd853ae04bc833b", + }, + { + Msg: "b3379a20affe67d67c103c0368869855a7a90955a389dedd90e43861fc6aac9055e82ed4052ba021e101e07c11655b5332e51288ae2b1d6ce92e0814a9222dbb6b4e70d95d23778c84f678be311eb5dae2d8399e3dd67c59bf5e9c78e1203cea243b0c4c6981ff15d7da252e3d", + RefX: "25acc538ec1f30e5e73d77d91c2b4c0200c784921f84d77796b99c216343a443", + RefY: "08d7f72bf8ec77f9cf0cc364e732f3f022356e243c0d59aadc0adfeebd1ba298", + }, + { + Msg: "d17c57e48adda2ff84a8f366a7328d6cd3067dab8386d8a83e068efca754055c30b179f3cf2519d4b8a05ba61264c4f78f5fef072c8700351eaab202edfba39e1ab2921eac82a9457797b76a22684a79b5bf5b5d7e1937f4b32a31c9f69696267d87bdb04de444951488fb5a8388e7ebde59f3411a8a029d8acc1de5c8dff7138539590e8e", + RefX: "0c1cb262bc0ee527663edc8e13f5fb508be799855842057b408e09bea5c768c9", + RefY: "083c6836f0e3affc2b4912183fc826a6d0e29f5e6fc8e9674b17114777d1b846", + }, + { + Msg: "c9f1497adf02267f9889be32dc0e4465962f16fbf390531021940d209424e46bbb74866b987d035e95482cc0f2ea290cccfca9258afd", + RefX: "06a45d3dad12dc35953a49ca05b3873a29b33eb3f9506dc1f331e22aecbc7e87", + RefY: "2feedac37a2411b0dba07fbec586acfa59f6a5e2156edec02a089795c9a3f22b", + }, + { + Msg: "f5864f70b0056bc2ac918c705653e0221ace2b071f29ae3c1df364c0f06755b3a3b794572571aaeb50308b7c1b6a99a1cc859fdafe359a30b13c8d4e9195e8b2d8d415aab5781395a04517bd38f78309fc7cbed79295957c6f981a21", + RefX: "1f5706eb28ed78208935034a7356a20e1a6021e6d10d22d70c4e76bea8e2f0b0", + RefY: "23b63cb3ec9ee2b80afefacf84395f5cb55d5bace41d7eeb26eec36b7d73dacc", + }, + { + Msg: "ad541316c52955527928806596a5ed824eaecc9acb74ec5ab894c3752a0b09005fd5d63e9188600f76ecf809eed5b5764231f0757276ebe540cc0a2b21d6d61aa727f43e72db909e4a4e623d9c87c27a4488aec6bba370f39d4f55ad69651977178ac5105be47bab099d6a90fd061e3b10f7337a8526a0aa5930c5b3b0473cd1c97a94062e4fca1d1f9b4952e54d025abe08270b8e03b5d68e9148212165cadf087b21a17978108f6e65586ee3fd8ec4e53aa67fcaaa9c17230441eaf7d01a54879d49", + RefX: "01259f5cf29017c54e59fd5ed71a1d5bf038ca28b5ffe78bf8d98681966fb006", + RefY: "09475534c3924f2a0e3b36c66c0d0410163da8d249cb63ba5d8bb5cded41de23", + }, + { + Msg: "6e645ff98580f30d6f492f06203a5db90e8159654a42966f5811272fc73d449daf1bc1a131ddc508afacef1a13a7a5f8c522996a57055b46f4d572e921869c13b079dc5b71efcbd52798b5c0c3ef7bfb3fa58ba4033e303ef2f03911b8287b1ef321e9bf0980dbd5e6b981e63c3b9f6b528ab8ba0cca5c4d3c68dd23057a80874bf1cd2da341e5d1db88e9d05c0168942b92b74b26a24644153d91c0dbd4f674caedba08a9c769c493383c30eec78b72ad9df98972b5d05925aeb6429b", + RefX: "2927373225a8da1c65bdb1da6fa904d8160fb833819073adeac95c2b73bbd402", + RefY: "1a0f09e0ba5809a7fde9ad37a34897931144a757f379a82789a71c0814c6e662", + }, + { + Msg: "1df630490614193de3ad907f3d8070e471f0eceaf8d66b9b", + RefX: "0b2b10954215317a4542f0c4b8042804cfd7cb04bfb8b159e49cc452b138c31e", + RefY: "29c6d2af3d69305fdcf7ca02d50f13583c626d3b1bffe5ed7a2a243734dc9bfc", + }, + { + Msg: "f6161d4e881e8495f0adb0cbb2c35c138fa23764d5899900f0203e058b5ec6c529457246ab629908ae0defed511438b6027af0dd0f621a02f07448dc152b8ea402fb43f963b5f09bd263aab391d9e13fe3319061b73ce4a2c373cb1f937611a8fc2cbeb49b2d9537c1b1ab080178611c1c52542d56e3d5fb66d170a4d3d2ad71f8c32867dc50e8c86b64214be0ce", + RefX: "025caf7ff1169319f9c342effe90a94ccdeaf39a00ad837cc70038375051cd73", + RefY: "2bbdf7c6a774b283142e08b5472ef9c6349991c6dc9d178f8080eedbe566073a", + }, + { + Msg: "64423d8210b174f1e44cee9225c59c7511c9fe12d18a08a8017555e8b5326573857067461da99afe57285bfd76704ee6d034fe4626cf4fb3845346d81aba204b15e527a4ff3eb8a239b7cb0dbafcecee356a0f0e17fc2f446f8dd36ed1673fdcf8270b142b45e19f0dffda624ac36dd7954a27d84e2ff481dda651581a0cae96dc15a4312b81b808c090c317aa905bdeb8d08b5337caa0537bcd0ceaff77a48efc0bc38df7b54363ec", + RefX: "100e2e9ff5399ba0987980fafa340148fc9058b8bcadf62ad8af17968334e474", + RefY: "0db48e40713dc6872cfc159a439663eb9f62c9f1dd9cc70c64191f63c6c351a8", + }, + { + Msg: "7cce3cd8798e4bca83a7ad722d31a26e752fd48b3222e15e33abe707b58aba5342e3588ad6ff0182ef911f5ced4877eeb1e53dc906ee65b49ca9f7bf6d80753b957d1015880bf846b7bd5176a1f4b7efc1a171b884eb33c90d586de4f6fbf5e0b1cde9660b580737355ef498e34a50044d6e4c4791a7a18e763038e13170978a31ce064b6beeed1dff89fb2c773452fa80a671016fc7e448f0745e536141b78df96d5cbdc430ef9d3ee134ed7da328c7e0cffc43524ea8cde6d5b2b53813d7d1ea", + RefX: "1bafd8979b5b9de249be73c2bd45e04c560f4f3d068b118f4976c1de952fb053", + RefY: "05b89de6743ee115293e6e11342bf50fad9a37b4ae809e68c46824eb85d99b9c", + }, + { + Msg: "a695b8ef6e351c2b72dc81411e2c5b2824b364469993d256926271406a2d31ac5d30cec055b9395359e1", + RefX: "2186c71ef24f23c252816f5812703374886cbdb6f541350bdcff79f0558ffa09", + RefY: "11dfee841fd66dc018db9e48c877521bb89a8467ae4abe47ef8170b2308d879c", + }, + { + Msg: "c3e96f21e8961c34dfbb00d5ec2ee5dd4abe923280350958fe64ed838e6f65020425241447f6e3a2576355fc16659a40a97720f7bdb153365322d3f8008d472c6a3678c0c14b52a7ea2a6ddb62d72666ec93596e3def7a7d6512ebd9548695a23253ae2f7db100b3dd581fde61eb61809cb68dabd799b60699f24fbd6b5fdf0e3080504be2f3f97596e64097b80d6209fb", + RefX: "18b6085cc3963166ec05aabb57b51efdc5570ec4f799bae7af342973c4432a55", + RefY: "036cb8b2256035ea3733000891f7ff6b2ed7ecca780c1e42671184931cce16d9", + }, + { + Msg: "6d217707ed23fdb747e8afbc78d3c88c548a435319a8d04859e3a02f05669854906765d29ee0440bfcfaaf87a61b3c94722d6582ff", + RefX: "12553ffb17b36df92a8bf3cb128724284595c41e3c96ef137bb3ad89cdfb5744", + RefY: "2d75e52ae29fa145db0f1cdc489ca8833d25baba68485b307409584ad4734aac", + }, + { + Msg: "ef3b9ce5b3539b91de51cfa5473c481403a00451a1875d45e28e1e84c23e92c3aef0286d9ad40d5aa9578844a74df587e685a229f8a2f7af7b6bedb0c51add2664a3461f223161aa3f3f58d51f7913090ece7b27a7333c9d105c129ec5666de6d82dbff725f9", + RefX: "045abea7147044804033eec962267ee056b943780c79be22c35255a304d25da4", + RefY: "0a70b0492af02d8c6e89c2241b3785de6c0c00b458f01418de9c5aed7c7fdaa9", + }, + { + Msg: "d5370ea834ea2fc748d39e9e5a592d855361f814bba9abaee5bcdcbf54da498d07d00f525a149ed8308c7d2af62fba2f3bb3123268bea65e049d7119a6eeeb3137bd6bb173f3795b78b9f9e8158e1eaf7e69adf19e36ad8f8638d6528fa0ad87bde7d0abe54ba4b1393b832a2e3d0ee89eb199a126fb97bb136ae7d2722dbbc3f7", + RefX: "0df246646b1b443689deee10d998d22e0c0455c77ea087f05fe233c0c82e4f5c", + RefY: "098687532d6608bd649d53be7d0cafed11df1f8211705e0324b66a13cb5d208d", + }, + { + Msg: "51e4808547d78066b15219e677e0f39978c7b9e73a72ffc8019751d18a1bda94b54a77", + RefX: "133efe4222763337bc70aa0508c414edc9d2e6e25020f311355e2f992452b14a", + RefY: "189a79d5b57196059ee06fa3a62915f94b27144e55716e432aedd3f7e4a940c1", + }, + { + Msg: "34765ce86111f5a651930d4a3fd4f102fd4b4697cf05e4aa828cb473ae2af9", + RefX: "026fcc11508e8a0563ce9782ce919f12019b65ac8258aed4c9cc42aa4ba3f7c4", + RefY: "069c1e80d583c2003a6e290dd3766ff2841de9882bfaf53109cf88cc031b25c1", + }, + { + Msg: "3204b7ced63dc221d4d848f861bf9eae72a1", + RefX: "0bf02f08fd61eed57edfea3c07b2edff3b507392efbc2b5cf2c8c31c6359d5b6", + RefY: "083bc5cfe651647437d3fe68c08c56488e026176cff5936452c72e14e0bd8b13", + }, + { + Msg: "27e00ee7ba4ca7d5031382769d15d0c1ace5f59aa69ffdbe510c49d4ebf0a4077d8bd2553b75655d5928fdd8e8576bdf090b64f3d5b2ccfaffa95da25a0ecdbd4f2c6185dc8a352183388c6736fac0a29c2da98fe76861e630266564fb47fecbeea463ba96125b23de0f", + RefX: "2130352bd7d9f4634c678fcc7d7f480d5800bfb571e3e6515c085e747d6f295a", + RefY: "1d0dbf2dbf0ddaa01fcd80a2b396d05ef23b9aa4c12f1e3fcfea0d1a19bb549e", + }, + { + Msg: "0112fb6985c93d8b27a0d3b6a7d65812b92e868320dabaae5b4e98d929b88e9f6912080a675d5a337811f245163ccdecf1465c731e47c582a7fb4139031c557e2c056a0b06fdf1680652", + RefX: "1c9ba1c2e09db086873c273be6c3b76d887acd7ba4684e0629917428862072f1", + RefY: "2cacc12e893ed36076fc908d56c291318d68d491ac57866b1418538305e41e7f", + }, + { + Msg: "e4b2ac04aa32f0f160ac43c3264c253049d7c5446b5878a4b54c11e24d26c73c9cee5f204c371504fca93fce718dd752bfd78047013e1efbcceb7eea60ed7b482fec84feaa1006818dd753ea23bc0d17a44a713cb4c26dc738a847866da32f1eba7d2a00a50a86976c72faa2a751999c13642d8a63e61dbb94d397c96d2475ad8ef706ea90d765225637810d5777860ea3b6cb52258396945828c2d996c680846fdcd1f2c7884ee432981eed216955eef1cc32f31b673e", + RefX: "2d348c7a4b0145b736077fe69e76865d2d40c567f9622e736e458ffd5fd27e5b", + RefY: "05415f4e50ab1c0404887698db0d8374aa1d8c0a4580e26e9effe34184b1a224", + }, + { + Msg: "c2f7a2e813ffd7ab7cce0c41bba1e76a8ed691fef8a5f5ee33f7401395991396b3fa745a5fd03d28f18de29ffe0048f20eb9a87e7c3784892950153a3868e6901b3154d94aabb5d8fdb0e84b13582ba3269a193fef5e1b103362075bd5f4b2a99a5a1a80b0bb5cbde5501c1ad761d4dd129cc5412ba8faebe518ab9077348cf3509b220592ae33", + RefX: "223229e0ad8cffbd71264692e2602465ee52887de4824e6a3f39beea21fa6192", + RefY: "2e5971716a540402ee82c823eb4f2fba806ec7e65aff3a84f6174cd983bb7b2f", + }, + { + Msg: "1822ce65be7b63ed7541f4cf7942a2a4dca20141fe1fc213c395c9120bade5c8f818bec777f82b2926051ecae317f4482447989ecc8ea12e5df37cb8d16cd6ad22bd76c9da1514c8f6a8d828e4dde57fb76758a7bb1a70d94a754cc71334f6edef02415ae6c08930a94177825365e44a1d15bf1defb52d33b40bc4fc4f8020e3094a7f0a0e7fa5d4408e46ac79c68ee98e5d53229cd1d7d7646cd11f4aebafa5d2f0fdb7c56c4966533da6fe53794c88660809bd24427a4c1a0398284d01347d75387323832326eb19b1a6", + RefX: "18b370b582d4852229c9d67a7573a1b91a8a91bd6a9aa6ab15e83fe70df98c33", + RefY: "08ed58e819fb352d1c1f10691b4eb73c481fcac42574164a83ffdd5e33aaaad8", + }, + { + Msg: "3556d604c5539a3e9215b446100b6eda6b95d17effef0bd5db269268a52e5def05efef99373567de9a61b4e68850b53840fe1b7350f6382dd41df710b4148b861d0a598b12e5d1cad06f33e0a5297ba6fe4e23aca2753f62", + RefX: "1a49df29f6559d184d211b014f7094ff57f6356c4f65050ccaa16e04b1c30fb5", + RefY: "30257ae9286b6134f37600600316a965e506b5883bb04017f8d9262fabe33d1d", + }, + { + Msg: "9bae7f6f99e0167880aec00e1ee9b25d0d933ea04d991806b3e05b04c173113bea0b2cd0d9e5e6c57d9e81d62e40ea09016a8ecdcb131a631c7be39d813fad26044d550ef3a2620492a12329296f975218afcb5e936cc1907302c5a520e56746a415c9024553fd3d8ec18223cf2ca31cbb079237ec557563641ab2ced47a21342607a703ea796b1353f478d0917563c1697d796723178249a68b421dd95e1cd3ecd6d33314c57e128c5561a7773fc63d59a668f91ab85456a3", + RefX: "295d3d8e1665406411ca902f01985352137e7515e5261956da86b5d28043be80", + RefY: "2aff1f5653e5b0536dc34c7ef2b20f3ccd8711abe1f1cfa2985456d83b86275f", + }, + { + Msg: "c5442c48823827e6bbceef8fb8b33f9fab0b2ee132af5668da99ed2fc3a1100247215f28dac9fb42a6dba03415e78d6df7e47426c2c42ec2b44a7e7db3eeaab06aa371744433137617e5fb9912d4", + RefX: "0fdd8e99d38496c236714a082cffc6845482db134ce30c5ed29ce046f21b7467", + RefY: "11efd07003cfa57b0669db4259c7ffdd3aed8475510aca2f98e37dddd6b82c77", + }, + { + Msg: "68af0db8a64f68e504b5c403988694b3391ddadcf23751183e2422a7976a88f16b4a33", + RefX: "0f827a9a34d1f548ea172345c6ca4016da94097d4a78a7172b1391baa08b0394", + RefY: "10fabbc7db86bdbc5d5fe055cf4c44bdebf9cfe2d9316dcb17ecc72cb72b5457", + }, + { + Msg: "9e8bde872ba9f9545ff1db33e1dcd4d4c24b9a34c05659badaea1aaa7276c9ff", + RefX: "16ed3931d76e776e0a818314ac72b26baec2e4e97f53345aba24f590fb13afd7", + RefY: "277e0c648f64035f79430aa7742fb9ad266379c4f12f253cb636c6916bb75739", + }, + { + Msg: "541fd508c2bfd5bd1d2e972adafdcaf69ac2c6b1d8ce696d48f4c811f6ad5e28fe7bb0262d43a39f60e1a1996b4667fa88c914c504fcd33489296c215030f900f2895db8f2a81e5e1ec84d0bf235472cfd142ce7c4eacf44b49200f47a163ffb9232b147e45e899c2f44bbd5d694fe3caceb46a5b299da0fa6816eddb4f2f2af", + RefX: "200c2562e9f55d04c1d9143c139a4c643343c140090bef92d789ed31c257cad5", + RefY: "2456483f31804c301a343dc33756342dc26c62c625eb506db699ea82f3eaff07", + }, + { + Msg: "8bf1f2967ef079048984d390c22561bb5a7cc7bbea6cb990d26439cc503971275b098932d1d163e979f4807abbc137ff479232561b206d0adeca4c1ecf5dce5557b42292c502e1d8ad34e6ec74ff0e354141e2bdc75129b7ad43fe2c378a43e302dd7e9f7f475a2b70c5664883defd138c63e7c686ab5d99ce0a96d7813ecffcc125b6750548558b96ec65a87b7878686495f4b17ae2b3afe2dc50afabedb0face79e37cc933200efae25d8b3eb30effbc068e519b754d428442cf6655bf75", + RefX: "1e939984ced41cbfc7bdf0dda276ea2a412ba6a15f22ac61c9d2a5afad2e7d55", + RefY: "01c1961e83c75a5f753e2619a256a247d619bc2ce5b98eb8885a1cd29dcdd7a3", + }, + { + Msg: "f4bd40bb9834c365d966ccad907eebf36074a8f460715e6c9b8ee76bbc1718789167a4441c83515b3e50dbfee70c06457a63552b37c5a1905ba0d54ddb9ff39a2130607005e88d34e01e63009ba99e627d9406faea837f6d918ec64c6904dec3b45e752804", + RefX: "0553724578b4698cf26d1b6f76e1720bcae4d8cf1ba7fe56e20183afe6c3f75c", + RefY: "1a8355fc8a9a9e713ee9e85007451e2dd58262d4ec1eeeda444b8af66c073de0", + }, + { + Msg: "5889d812746fb275b09a15e815ecd6698b32cbf835800ecd36e16462a15e0cce98da094c2578acebe69c0f04bb8e44ec9aa3d72b55237295b796d2d7de07f986b9738dbf154ae7fd4186d9f4c22d68eb70bc1472462e96", + RefX: "2ac97f9e8d48faf4d87bf4924b008548ea61bad73730d839c45f55deea60215c", + RefY: "1faad73ef1cf6699f0381ed672d4a3cd8c685655f818c2024e708d995e981eb3", + }, + { + Msg: "a8d2c64dcb7748799606e266463bb93d110dfccf506889570a9105ac285843ac5734546f201024f8fb570827a958b7c3ceca342fa291e7afd07082817d97b76f134f0b29cc78520332d8b5741d20339140670f25bc423861aca188a0ca9e1a65e174aa7b2ed75820538a9bd9fde1d034f75b8844aac7b7e83bf4690a09615741dd96821bd59991cf1a4212", + RefX: "23390de966cd6ee1359d65e59d4e807fe9e633fd179246272df2f4c5210891e4", + RefY: "195990b0f20dbe0d3e9a8c2815057785661b846101f25fc2d5633e124f519dab", + }, + { + Msg: "6ee98b7bd07cac687b0b5bd92dad2b755be7d92890e3221c1fad3688e2d7863bc5de9383b0ab2983b9ad3c2d5c720f89ed927432c032998a07b13404e76aca463551c6eec2568e3eb92ebfb9b9524300f7bd90031618d75f0dcc9bc4699f18f34dccb59786d3a31e1d59cac489f4fe3b24e4fc16e2ad699875242a43dec716389b5ef9fcc1c8827110df84516203eb0b30e99f030bd1663c9b7d5bcee7f42e64", + RefX: "13145d0607babe55ef9fd23bf41431f70c2666a31c57a8f04acddc0067a037a2", + RefY: "0169b73b299dafa67afe0c535e0fb8b398eb62a4a2ddd0bc9e34e107445449d1", + }, + { + Msg: "26fb817a1f4b25a10af7ea9e6f646409ffa7a5d5acbd346920fb62764d9f184359beeb0fa487a055ca6861ff2aae7d2996e23aba07964c2ec17e31ea54aadbcca0bfac0f2b1499c50daa65d5e219db337965e586ca625703f0052cb1b65b4d5fad72153efd5348b3dbcb0311eb9cbc9f2ed1410e7ad9cc80d44ef90bcb9c8cede54e55a27faff09055fff3dc054f6ca890ff1888e8fff3c0b53da7d087f1c54313eef4d8b1a7ad0f35bc7cb30ee512e597e7f2a7e3df962867e29468a9c6ac79f2ad770b897716fa0602df34", + RefX: "2b7f6405f3be47cd80575d3e132f85f553c1766974f3189c0f13e750908757cd", + RefY: "057fe00f6640b1388dcddb2bc1f9443fb6632e6cad253dfc7f341ede33fae286", + }, + { + Msg: "c9765f690930a898f3ad89deccb78088adf90078619d44d4c5d65bc8e83c83e064a07a323adc8822948d", + RefX: "23a0592a944975daa8519c90022c53bd96227b1677e9a8260171670c3a65e152", + RefY: "091339d9371f514f81e671ed92c3c11dd6ea902244b8b29f792644e41ae3c55b", + }, + { + Msg: "1043e361a29bee4b5c37022ba36601d54a72792ff7beb6b9a0e6c5c9326884721d63c26210a3d8a10b8dabc174e3066a10127360ab684847b417ed944a775cd9e9504b3a527d1bc11a34a3db07804e735cbd08cead011c913f7b", + RefX: "22bb016963759899fbe18bc2c3f4bdb2fab0c5e2ba42f207a7c3ecfa502190be", + RefY: "0144df21a9f5b6ceb58e17e0a94f4e54bbbeb88121c0a77699113d70aba98cdd", + }, + { + Msg: "44c8b251813dcadebcc8bc9a40dc9a8b4e024104f327dd1f3e537e0407123add6adb591cb55f7855c3c2d24d5c4fa68c58247ae1baf49ee52d3067d52df19f5809417ef9b16d8276de6a440cb8b1d897b81f532ae089af9daa09e8392c9f360592aa3fa667cda1675fe7da345e3b0639c19ec89c50514475fc2d90d8fbab1cdb52194761b8e439e32fcae73e587a68b21e215b3183320674c885cf670a4a63e0bc22ab", + RefX: "11643e0e5828fcb713a5b56d9f57fe53168b5352fda3c57e63963df75502845d", + RefY: "2159b18b8bcaff56f454d1e3ca290a67757d3eb47b6f8b3098d5a399648650b3", + }, + { + Msg: "582cd9ff3ccdd46de72627d24f5f57b24701b59a66cb0b7fb1c06f010056d8e561982f8c1270aa56094a6177999f4a22b4fe06f6eae01b71971e890b69f6793431658fcee3707821a2f5fdd6345c7bd9b30df29b0237a32c3393ac89df3ec6675f6926f7009e245216dc7ea96e218d036e2ec1cccea3a4c5082d7c1293588b3bcaa58efdeecd6eb73b111ec88a89bc0682ea187170aa2e65237ea047da126800d6ca83f08ef827170d5acf536eaeba38ba01", + RefX: "13bb6a81c43f8a58449cbffdba36af0f659660214492022095f9c2021c7c6a4b", + RefY: "202acb670ec181e081a51204371fdc223188db84aa37d6e6f7591afec9a48b32", + }, + { + Msg: "41c29dd72f6f010bf64e3640f137e27119a010beac8623d7733362846959354ed6ca623e32af26ca9916ddfa9d92cc73b7195d992e59fed25ef10585c8e35300ea15b9ac49ab1b07707f0d99fec47f827ccd36880fd93892bf3304a4fc2ecfb8c43203089f3bfa5b972f37e725da641b2d05defeecb7881af7b9a8953fc57a0b697155adf9aefa782066e0d9a912d19816e53f9fff62", + RefX: "2133f95e235d208a4340fac921ffb0fb67e4e21f295b1f4c9cfb40ee6e930455", + RefY: "16de9ffa7918bb88ccd17d7c987d5db86d3be0f5d02b86bc944e2e2a017c9e8b", + }, + { + Msg: "0ff92329c3699d4ba378869aeee9cd91d5ad5aca865612333c1d509351be36c7f960ca58e92044c3ff8b2c262fd3b33d78fb66aa56ee71ce372f81eb251a200fcc8d2b584e7b1d9c71a8d6b32ba619ea0f2af294d7726993aa3cef235a051a0bb0", + RefX: "2c68e7fe3735b758a3334dccbca31271c514874fc130988fc804349e6a2bcd01", + RefY: "1dbf3cc0a4f6d05b7b9bfc366bca2ffdd1a2ac5586f55bdd5e953d320fc4578a", + }, + { + Msg: "86f000bbf4048a9ff2398d3b2bfc9ad275260824b723ab1e1b81f8e5724ab250d6d0d1c37d161e764ac34670a5e74a", + RefX: "19e350eb92e6fa21d998dfc9ea29e9b87647169b03e27a69d430a9e272957b92", + RefY: "0a32fcb7c856e53fef696618567cce085ac5bcfdc58a0ebfa485b36f33f299fa", + }, + { + Msg: "a9e66d8c0f6b486d0a354a0603b08043f2c39f7307c6530497b2ff2e0d50e02ec36af43fb81a3db56194f4ab30629866817c84f223aab5b2062e68dd5552da12e1e51da0d9aee55744d35dc4637c1dd8a05c1328c37220e851eb238033e67acebc924221ac5cf2ca933003b691d3b97db571ce8d46f6092a5f53c4854ad1b857229a881a859bd2f46df1387da4b3d95dfab7720fd7e727f81746e7eef17e8442212a9282119cb3d7e068dcfb3c7fb74d88", + RefX: "2ffac22554e630b23c70791fb3ca05001adc1d522d14d3fa29a25b4244e4405c", + RefY: "2fcbc3f62c297ea125477e272abf97862319ac59d1c13b74c8cb512dfe605b17", + }, + { + Msg: "4d2114782d7c3007e73bf4007bf62b298c389244d846d0b8bc2253a39e70", + RefX: "0c05732c47339eb7a64a71b2face4e230cd8e17db80d5bdbda54d5579c1442ef", + RefY: "26781d2945e2a1b38b968537d5b1e79e3927495b3b930fcca4d0cb9492b968b0", + }, + { + Msg: "c1fb97fc3f9cfbc0fb382462efa6feeb476878b273bf07d866ec53bb936d0b46bbd2c1cdfa9e8944f8902b6b1a8c91989bc757bfd61e22e546fd46dd47715786e748d0efb592899dd6017e35a6fc773c", + RefX: "2aeb799cb62ba6a3b65fc886028a26988b1c3721a5a8676c26c51c8639ab51a6", + RefY: "09b31b6ead69e6238624c6b542b7d761471857e9095324bd578a6f4b0bc7ac18", + }, + { + Msg: "d919f9b699c72584cd0df474cff52968e543e5ef3f8697e5aa218d914b44197faa93900d339ec90452410a4a2795921d74712b7f1331fd902a31b651a96c3607a06a1354333f47745fcec138023a8139842b0e1b06fa2a3c553e4c84d3461dc31cb95c53e00a1e1362a59273dd7ade1bcd2176dbe345ef02d53ea562e5a2318e479f878f8f7642e867f71a73c334afec1b30fb51c3e56778ff6b4783f777ead9489a1c5e10ca068ef29617a3ccd1f390c610278fc76e9bb15ddd456612bc0af81a9055eca5467d", + RefX: "25a1d5163eed54991881eca0920f9cde36cab65a98f6db2ff6a9116a21100502", + RefY: "20dee5f4fb6fc1ecadbf5be2f1a34eaff40be907a7480069526e8b9059033583", + }, + { + Msg: "58284b8b67d863c028ab57e8d212364bccb614bc67742500d3dfc377f6219fad4913d1dcf068e7c6704a3d74ae2fd5e69f1c87d14bf03c871cbddbbb2b37b69a34d762178b95e2eb2c4e385dccecceab562f5bc592", + RefX: "1f9600724188435b4c7c2c69a4e662b15463abdb9fd3f18af6884e1f813d5ecd", + RefY: "07e80d98d21788aa71322475275df0a0f795ab76267433e53b28858bf4993e57", + }, + { + Msg: "28101bed762166116ccd4dcd7fcab8e6b29940a94deed2e68c13250f625d683c437129f17e017b19d8f71638195b14b704a46d1a7d55754d", + RefX: "2296586c7f8cfe1db756bf1a43f2bc2f4485cdf08e80de867e825272ecc5c634", + RefY: "0ee795f821248eca1549046aaae1282b0644a9dcb2061eeae5ecc2ecb586b61e", + }, + { + Msg: "0fa951afa4eba913ab48ab1b3e2571b2985da1374ad252", + RefX: "18f2928074d93cce28a06c4555c4201e3086b4e3da43d84c88ff5429e8c2e9e8", + RefY: "0203321fbcf8424b204595ad4cf35cece3463de58be270557e5aa503b3aa9d76", + }, + { + Msg: "7d2c0d522d6e77c1758d3bfb01c4ea0aedf8f476da6e0e9bb51720ba99b5a5bfb9c8c0339bf843ed2969efb75414c29da27d9c3339e00c1daa03fc31cd9d02409575525b69f7a5d973cb5f58186586e5b5a3edd52cfdfe382570f74bf2f9ad783869840d9eca21f716848d3e78333aa8c0736583b25a7e0a4ba212730d7af9f6518973fbe326da29fd156ab7ba89bc3227f1cc6f68a887fa7231b054e6a11e2b84", + RefX: "081983e02354ce0011ba687c89eeacd1c15ef8bcc27b3abc6923bd72c0415c7d", + RefY: "025c4a213ee1aac4a4723167ce5d44e2a5db861e57659b54e3245f10fee197aa", + }, + { + Msg: "f0aebc8b58a7409dcad53b26fb50a0b122401b602bc68b7caa276692dc90a24e8bf876d6db3871d99e57b7232c287f85c55574e95e54508d3f31211950709c5d60aeb3bd11e6c3f22081f3aa87cc3d871fdd2b04689b12947a994097a6bcf4a96361715b23eddbdcda742ce7c35c8cd3ea80715f1cb262c10e081e0489ef06e5025deb83f05663a087e78a65e80bfe9939f6e5b2af14b7e38044fed21da5a27a75e0463b1b044580102febdcaa3f89f0b7c6eaf535b065c3c9adcc19211cc0", + RefX: "2eff9a5cb1fe5c8f9e5ded9457dbb199755fd114bb5e7f345a083cf7d8a44d2f", + RefY: "2d1d92af4bb01ca254ed5e6a5cd291b05517973b1c28316d0a4a9f6f41920f9f", + }, + { + Msg: "ed5120a783f826b37cf02305e53b58c4b4edd3fa421de3fbe09cba0dc0363a009b2cd73e0d48dad8382e29a9dcebc5d1f806b2bcf8fa8c144b9b1a420b5f5df4b22638c89c59f54069b4baa1f09b734bb6331f4fd4da7ddca20949f709cfc55385688787f0f95383890c8bd2788d73dbd26bae6016ae2f3a270855e647cdb995fc5e97a7dd841bdfa295f44f849ffe76dd0037e37003", + RefX: "0630f7b8828ac9cefa9aea166bc1415e1f71ebdf65c27488a8de27f5cc68969b", + RefY: "1ccc8c258553de793f039299bd7062611cb8ccb2d9fafd404cf00f1f470572c2", + }} + +// To generate test vectors against reference implementation, run this sage script: +// https://github.com/kevincharm/draft-irtf-cfrg-hash-to-curve/blob/42cc474a11117b501ecca31f3a288c5513f17f15/poc/suite_bn254.sage#L29 +var mapToPointTestVectors = []struct { + U string + RefX string + RefY string +}{ + { + U: "3540903031681319421922757684101610645767707797048988415875375111724680581685", + RefX: "8075871960767046579231430403985926277223410823818061304251976251393112450333", + RefY: "906535411243285569638264840959243001417172892367399608998007435385595449341", + }, + { + U: "8907521814056845701802348140424269446568701586099685087550074745505454990277", + RefX: "21327796494947423405781055484721506997911420687569473755205793150767574651200", + RefY: "3372936415674007959180395606556373867269842194129649068337399034827190551419", + }, + { + U: "20326462760568587868629484809115194097854000284430645425127344852845016335889", + RefX: "18348050220125696793834103828885788353830697599990912860791666991196360946977", + RefY: "10142397021399531924792542567727608849689087726487616526590751328276153549731", + }, + { + U: "14002706413544512086011313485260721134492113971201943123855929099751712401330", + RefX: "5654319571910195119875017232265243457653084807005590545621347499927356452482", + RefY: "8662841080934442035292875987773120781238510495992762203740694041320765040430", + }, + { + U: "9029964684230010889644402877237695563306506518734238145952077172678272239729", + RefX: "16232949366108770005106479722961969861572226261135831246834195858561579527625", + RefY: "16632263432778334793843525578889065288090857901297212349013142811533289311567", + }, + { + U: "20433602381563545977054785883450217099379321166836749429260180850324759180953", + RefX: "4671457931779870448235324152916975560386276188307637329988945739541761987730", + RefY: "9336940063791428778420295589690961823181358802019460302623215268762121348201", + }, + { + U: "5335020282430529526866363296916609170892253867928278933284946329808645406914", + RefX: "13511993889994125879986906436996720237735840534787708275918961750881866930407", + RefY: "5452280507104892396937266548493434717398981748851885316505437251178962432970", + }, + { + U: "17909031097814602972787271033907322322682505065502103387807122741675508525932", + RefX: "3968208616398817559370467075258265467304843199813320907457957811170945569471", + RefY: "411812734546354330429721238446614388649294261844483340097235715346756950344", + }, + { + U: "14007634763071840119786278388678832896273325969651423572281001262773269413916", + RefX: "14674165254741302030744297977338949717176910924161245564087326032426782137450", + RefY: "18996197329793236817941755524120946677589883973906219750028782480637717391422", + }, + { + U: "2949710584866298192086880823641272178630851598870372031335849721701027539276", + RefX: "8762718150926382445400843569294362094360060172096538684941577066080799009602", + RefY: "11344754567763377417302176996146656475165561290576940456963709564061851411242", + }, + { + U: "17383857167762370968803803316714149394152600828896089004718167425499555537356", + RefX: "2056118942010201082306872870811932611931581445470171989087857346812483467890", + RefY: "5395818438623909868530758378432115577031302608349300059391410496646619059318", + }, + { + U: "16790481588467486713138481704256336698311563712450310047269422977889374516388", + RefX: "1244153382945416406859808477461905819685000811144692599882574601172454185592", + RefY: "11005663113685614682972728000199587767958979799959797724633848891562377644892", + }, + { + U: "16410983150463102790287217555320908756321069891645948665271370719448108923597", + RefX: "3866633272267901463168997899442372181976344313323249257402237563356023986760", + RefY: "9434714177495785938122095447425801929783524568841157554233357266023252757775", + }, + { + U: "2433442454122184272617033160486387901462318684966629932705457004420603082451", + RefX: "5544133503695444340326585070810296614378975915735186456252596388293498049009", + RefY: "10709060995929829364389218971666772273251880337856620875203737436816886977679", + }, + { + U: "18959206855716008460622984642635151593468692857930701506890537436877837696823", + RefX: "15416783625919178451611114568325911297447069908781276319437930259796879948125", + RefY: "6332492582995051849320005498209320824634268427814609780607141568406455889345", + }, + { + U: "13861348058030494982632401477306297479904744535148547809848423711758725493576", + RefX: "13301591011506564569021674530620915183071407570300863038512044196475529722492", + RefY: "21388601993422392738280605974194313626223082046005828057019191565606459133804", + }, + { + U: "19637142311035170445233573916482267472096305900739925808467555010053478507481", + RefX: "2056819677727344689271141755876576537645782642578928162916091715156111294196", + RefY: "8641188300015616448113634043167827096788369037374249376187951860873976409863", + }, + { + U: "10658965105227053363958930288090648657002989022690659856339205525819235132353", + RefX: "9193641954609980513854610714370942538384035716634917205948893489217498313663", + RefY: "16508377837363234485762981205271735061768969231047376968142114183215146230161", + }, + { + U: "3361362665589439692299870735596614121377339730623636050821802877909759385982", + RefX: "11073224648779772743360439236421771510630468236123219810616337287640280684971", + RefY: "10283249426188346824486482042104073163070494617861482844553764383239312667300", + }, + { + U: "3321793827060136826359273867471536653646264093022988184519247672863808453716", + RefX: "20200808255082090287573242190345764334904796012930913689115722258062930355602", + RefY: "10857286370003909416553814960624874125596341813775934135098065635555759979836", + }, + { + U: "4105616314159184650534401451001122222623621726058634042105587448953075757559", + RefX: "20439973923616645087878756088287414207678605906778629547198313163700481444580", + RefY: "11465333749687228977870187717749105577828156965673653344917222930529887900257", + }, + { + U: "8205746022086183367563317986898710573846301193968749686687635677607742914816", + RefX: "20270032805122175770572217237198285932047514124506018986470447411131609012824", + RefY: "17591689647274062808094383629274943543106166373173546469249168833184100278764", + }, + { + U: "20346456022805101516283131488128346236969434847500364845104993514244161746249", + RefX: "11057729909227478473421198311859888412220106142745277764370986238065587447879", + RefY: "17204896840226805130135368588660858256378653069638565994827852227265536288157", + }, + { + U: "14357795930062406940788481254436486035920909507539795902117022655556791227916", + RefX: "13682871859404963221572407851039595829965421596371541021424896306912015633001", + RefY: "20601831244557465897247174285344404956705913864783914935466870691205820103434", + }, + { + U: "17818077721740127870873792588234276924208210044284679441094721479727008761790", + RefX: "18269386556874751323599045747631381689622842969053502491944060994305059308707", + RefY: "5169756520337142591137240840470416978342185009815636771141005315789126757168", + }, + { + U: "9854604512352652700751689736506725574343719780247475351429078107861209429934", + RefX: "1163997182489158065402714654688284744890915157778379863909649028919469843084", + RefY: "13431766667954627887698273617550211127683503070462685350738769553639077592124", + }, + { + U: "10982836668145263757354238950893041871801751410126486418843768742873896779755", + RefX: "6105470393193481750415203800976222901913538754139383187626724306724309453009", + RefY: "5174236419912771748226389099084966647896187469612153589331371098673542334111", + }, + { + U: "17681946780604570072558150343289231405272311762547278438816152075658995382181", + RefX: "768046473043131793935520112472404702413793060033926762310163322534401484574", + RefY: "5786045719347289428498441169563868872782078847774275217246977792001031715117", + }, + { + U: "13417341180437064545099512372086562786911772770997831740627007628572054996229", + RefX: "17847643637901956894838339598152201873674129614563337165256090088679540086483", + RefY: "3951182901820163922255277611647297902601920693222706218146435130884365247261", + }, + { + U: "8298009344150038669488315826370087136562718528964641682988943790850607837803", + RefX: "1907395333032386220216385793574491237411257142601372140457859064967163859099", + RefY: "8754971731875399485425417375479210601934642064466332163447809811818986353429", + }, + { + U: "959680025930558147545929799625176064808497247396301084241509445405428581343", + RefX: "10389366005238094526655585263993628107285173596753418453363191535106113972024", + RefY: "4770981248939938523845539671737648980793741369704290943856623398749547499045", + }, + { + U: "5159700360513260156811719529090826265481072469631260698601469060426405420268", + RefX: "17554929871239236174398154807623807888858480888475547988347940451336944390871", + RefY: "11887947446853676454663381377374921472631589209906901308393769188320266565964", + }, + { + U: "5237781868066230530504070848365475067173446285386759612520696142436666317113", + RefX: "12826486579501214179753842315511542570579467180473517128656557834544946821723", + RefY: "10607432879247769398811685693660497198183567898220330571048266001095469045963", + }, + { + U: "3450971351247148754449714611007389685229688900755885258154912534400245314658", + RefX: "10933380063192101127994000407732558837268593142324399167988092074817498968900", + RefY: "16329944692568633476680910079946482848623446581905744300573200181009666531522", + }, + { + U: "5171639743939125487870239591994201614953606929723072606607104580251012762086", + RefX: "5689249468690134958294095815804735264846293728116454080080858276741553266723", + RefY: "9811080731257438290669293965114114965955714737935804261165606340223003251446", + }, + { + U: "18641474263085688309904077125619893339819726948003429145858409573796342244527", + RefX: "12678180312939930496228046421012908771081557480467315302260067409666800894637", + RefY: "10236519912137131023660582936040712372851792019439668822323774146924863569311", + }, + { + U: "20051855172913422446896017846696032468770162283629530696952815300667296162588", + RefX: "6180551986697365070679530447100282765002529968379778690861796576249659853157", + RefY: "13017410398834104173550244292980013437785592112231334718912210266354529851842", + }, + { + U: "14942292146072175248319106685993351535826011944101270405219319797971656292744", + RefX: "13687026558270117625008373319817963978063303817198636257615786878512680947208", + RefY: "14630779003732493059298175628645800901630867087609856275491019667003932889878", + }, + { + U: "18700043710431712167802774176099066434708751131039930065653196222424186955420", + RefX: "6896574659741004634451254107957495856689923076671561473791905692814287654564", + RefY: "5617937257226282767395161722769892760979582126640415197292409781172108866610", + }, + { + U: "6870048960707290013721573476832900602137374825776988265372296396155920951944", + RefX: "1012279724042611618400474288285174188095984560551106496434279184001923425555", + RefY: "12186244560977926999313802453429416480722494640866900130712708943464451628820", + }, + { + U: "21007295340503696541569993458322174715252737818932937255468741948440766914433", + RefX: "10066492564774065108710284107607047882778491787083738859675472850415955041542", + RefY: "19814942783407558424059784492883145421206870681574745375184269709674007909637", + }, + { + U: "18616023067879107381450821477233530214053764300417896126601638004279163779019", + RefX: "5657270259141275923537625483490969411724102216467320453633214949112166825085", + RefY: "3551080204165848341973298217653282659143611671557028762166356897108209433859", + }, + { + U: "6747632218298289561383250399556530379767255269751363085528178614993910753232", + RefX: "10751301931751438450630090750637023709043323043415076165453097088292042352048", + RefY: "18339809093822430147137942159963236564896478500819683177979440878300222300552", + }, + { + U: "5897220950594138032665300801451505868464777111082400165189022896396398024895", + RefX: "2417621556084860004033833871840907513366358856464497805183823223655421366401", + RefY: "20280073167948767345873783906460481990317755570348386405245318893413250713743", + }, + { + U: "6018069048112356536877320443389243026502418599310637008049666109754099522312", + RefX: "2857453632912781199537008070778975184098813588840471092663288336297342668266", + RefY: "2019754425687923835368695352066583491027468680896719097302714398516411162718", + }, + { + U: "13542801195178707486197287302039037537518782460377646104044675550123907363594", + RefX: "2269331311112618678393089449882109839412112711373229445059000964687131283340", + RefY: "3640942272524310260773312652720052570270590177915577026673120929833256164548", + }, + { + U: "7824888989146726532802138856222379840788390785541810095477692789058050048652", + RefX: "15922707378303568360474666922037424137906120811520531639326796039828563927865", + RefY: "19113010469861118210646120000049057132051981440848400855209095449801308888292", + }, + { + U: "868889660238124588572753459331904015113821558394559021852873989125752810267", + RefX: "4059205307870573604174023657640987917437360210251129824687595585303627844513", + RefY: "7618091516534771896283958133605776929611271350666085296858988087468144054751", + }, + { + U: "6162275633283962530377357657734738015278057698528645664523557989788716856580", + RefX: "416543586191988291667934857820823825924604698676288399260197410823968097989", + RefY: "16204740080554414303961726297431825667160934299130683934816282209547496688990", + }, + { + U: "7383062311118420473825115652397602717732688706928071419625065524533661087167", + RefX: "9945835800281105853501099569161919143104976202275556298142368175382972960147", + RefY: "5087328446156979871091797144613329074722604982125262685352642275931763567519", + }, + { + U: "8979360366270640792494721822647167328004941564815586254557129227709841045153", + RefX: "20841203709581111366905010977147774800376678850888619018991605657913128031836", + RefY: "1689792318412154248870264634541375172948907200044263071080097079182322887023", + }, + { + U: "14976694410985375468443242840462049405992849420618595373001895787133805267842", + RefX: "8034809969435347000177841068180880504708014177706072708684014357087320779705", + RefY: "9854698206522474247819197584381449400308436846287630156338646908166784219264", + }, + { + U: "9014702115955050307745658851714093965795592075088820838392580038383158986252", + RefX: "8945001359525421617555941579242224591369941427087341897590307870852359146731", + RefY: "8220682783111505169611848331439398306349656791696892297646354146548169636594", + }, + { + U: "16857340496572276026022811032308924508269060388263380783177758988787675874766", + RefX: "15460987111317556323074366256206958890478568460596235776446283017537285424269", + RefY: "17404853442049070930399015367659092760387850126955636758782086025720449760692", + }, + { + U: "18467042022038710559392731993035670287677882934047083440135766159191325139350", + RefX: "18932138066722789698759574162049607286768278437847839333483860333996781759154", + RefY: "7645666733436596396422132451747211247943909928038977207940290256490942021626", + }, + { + U: "14211036643537461128497265923282476826171710256595962070690531321084329676087", + RefX: "11600987382755506962838937863600301468453097613347048150489305179296560197086", + RefY: "15996697227784241707658871957671421811287281548725907221069615350058443679297", + }, + { + U: "14724017461783757968000502024709113513157524804322193147197771112753867593047", + RefX: "4146097436065184949171561868522186721313483949809002859506381893266501314028", + RefY: "9881454816254594760630395538129986194113823902104251224544505774802155146695", + }, + { + U: "11765083218269581255979746940672110730122095276762151365965767658032977680829", + RefX: "4881136171121866225860077611104922391825353386053125521561859959588095423012", + RefY: "1950888419445644525502464981649542398736339123819248924063556711974349682601", + }, + { + U: "5626742600047913637877219155151127019664554736977969895306360454489904035642", + RefX: "3609623199461248343575869437922406614728289804752923439871176186806025210854", + RefY: "14829215095971898888078516257933571597063376263043801017368748665567270261534", + }, + { + U: "12333066409412292650994358986919571423922379461287749128567280437045298908287", + RefX: "5791905772282190368834107191920497584401200290793780262076956795971466027650", + RefY: "18136742501515389969408790443012660574467064287385540304963894067198226481233", + }, + { + U: "8978370544836483486154061726515217238769195389083186694233491029858376195968", + RefX: "21836392599546137000875403192993052168648044234113386999143749364030569932437", + RefY: "7663019845591664572581053129113249360324807902157548475925689053464488356320", + }, + { + U: "18825169713217005727748530245426571073253677761080290343024652976356853226860", + RefX: "1508062671793137959256783116853672677617978497723983184507508427937411589269", + RefY: "20500639685216218477276318569524647357170076158933259745970546848348704066550", + }, + { + U: "18436452826424256651049247969205396612934077068668120634726131217643027549889", + RefX: "21780387167914059042013117571145515599721130136890393811922311862865446154935", + RefY: "16177023221595080100353702332954644576170466647523473313193409560410580729031", + }, + { + U: "17355485764584897032800128013049280613860523034486320835452850300307125233185", + RefX: "860621159190264191289225535251858122494622333110652741379167513123162865530", + RefY: "12570062079520376403603763797069021184464922776403868098446943510071700313709", + }, + { + U: "14734627709205528009349676285060385876851640059452264067029830247241836117561", + RefX: "11496476311290768242743747114119095008354756571692103947990790303090147084666", + RefY: "18875256024952855893833586646077048194450661295656882101121002237047665283297", + }, + { + U: "7289665490701157020728643483296407508765761598115891108477009783711605513820", + RefX: "12528535241590438233132238786015499944452476285652951372690673804784959529195", + RefY: "19463528582819159940607123918374993468839133702573040122812633915784575105928", + }, + { + U: "1045459674045620689540259679072695360218681371106853260282344919695532561136", + RefX: "6561036676323894884968287936201498517437811745853056865074287905838548592561", + RefY: "20400755533603120178540503899683895922514822466778022073393010400383110330176", + }, + { + U: "14031627835541484016005009555055850645377038193558369818647809633850337735711", + RefX: "20937383863907643119883654981165902784254927540907394935508907453868543893185", + RefY: "9349444235908320064888556454619022193325983451539457788174649125715279451719", + }, + { + U: "12047453587314401019838425413231919758262319944213704970276159429041916330500", + RefX: "10745459974199364883240278216826798572555588776651327087754013314673795057212", + RefY: "16371507864437552543512964685348538016151136733779584068220877131100865117884", + }, + { + U: "4614444347367658998263275793458453089645457263752010133367663055788833084623", + RefX: "21033478464815905419241528027003779974169540695901694459586332859648207762660", + RefY: "14313722841738556669045867872822816810443364128100068224353764580249513359559", + }, + { + U: "12796894950196423006317307319766841546515169483682631606802790902779372384919", + RefX: "8478273219410917888924762919896846697118699290121232359689697557442425256364", + RefY: "1866373034920539060162325762826585804499634420758776728826646582430525759777", + }, + { + U: "9696411275183769463226227419484757939147755212000139878396822770310753982584", + RefX: "4038376261140505087569987381999453128597023754894284340057397293463380716247", + RefY: "2193074241308111055679448350979328343073946509011353871758426624028738891896", + }, + { + U: "9836298098699474430584234261488847356046612436051581046377824355741076613072", + RefX: "12007053592448007592911591665699837514375957641785994382975691321862628279924", + RefY: "15387529759089648766976987407976485426382657350236674801439696863025163638528", + }, + { + U: "12891790162608410977227516209753618648621446834170575567725254422589351690334", + RefX: "2878599422321779929938620034965400128531849860867850074659125717751844720232", + RefY: "7355785438293065555998211817081205172655774684736150589376695371859280521394", + }, + { + U: "8324557636496105234330382671614548151144489100004729728062548965055678751338", + RefX: "5293330346614266422991619279273584475126940244973355977784758324873277913291", + RefY: "10812116277837549043555605948566445277012276766284971660857339103575599147984", + }, + { + U: "1861906554018186765017829803250947447455834801751407695813540213136540498425", + RefX: "21685882468331679268702931402191452370477499023618973691939797202593354355363", + RefY: "2577118300087241826613159633560269359414653175964461203715544339572798788013", + }, + { + U: "6619942493381680275714365695817565342104365153133818637803261565475495213508", + RefX: "17589698384717863679870730802596451468519688534109654505812325185427514766714", + RefY: "3938539299991735612466149269531793701166507042249969682443336610551149616596", + }, + { + U: "12739471818862360836725716878137494000506628309252284122544328301595603728726", + RefX: "10744191666569853449035150835608963671754645829797997146651433910425407756708", + RefY: "3348716157169386230872306473017803191233652031005629959527850815417961318230", + }, + { + U: "7687472040049259136739821900068149587366066903318966790995685998246199241337", + RefX: "21191362061554121051862555177832632287391528859420625125377761278524455501781", + RefY: "15502240890072164601442185459999739267575064532205509943525446495464631825469", + }, + { + U: "5616498791021556893317766518132167233720650310352259798105174349755373014695", + RefX: "19764557882278236676669128339474101998700710709865412481688887629506635524197", + RefY: "6986122344182541423814288622018257733067821611965485122061231500209619415673", + }, + { + U: "15492830701690543517962650280421735949633440687694566953616131723275879632117", + RefX: "13519082637524751545253375424488579958979212805387019508035465612440955917651", + RefY: "11732886210372985736950555654679680621687111749976441002948702614043339976015", + }, + { + U: "5803865058239019191960479631641795549664039182437584189035773410969414757728", + RefX: "14693362878003478231056345775077565097744280414299537881940053884507357549825", + RefY: "11289996029919576663144892356962574350888990262981799593242287995465678623058", + }, + { + U: "11464174271831804833926746630266712635297601484709428803117133625625995075550", + RefX: "246513390273915744796964815012095059285441580756976047864479299366216934035", + RefY: "20389148729729759067426520393377409668015245061655657048415546108872138683948", + }, + { + U: "1319186481770884465500030409835561375610441773683303826374475846382483609234", + RefX: "15636285360770155961098778900601080593198579235806517994684558904539214461543", + RefY: "17647113030296473167010070222335530083004976946632706446661446860718072955282", + }, + { + U: "12834313201133716098900195475364438661557043137012398584732745040463469346632", + RefX: "14430171861562995555045268467969422471003296465181689680063122827333571988844", + RefY: "5371828597965680084869286056021110506862484014158508582191967130806417052834", + }, + { + U: "15438318649506074410692234337038245656799424262724425911455920964595642661796", + RefX: "14707953080353969848778494321939057088475148534248139453879478088281829035383", + RefY: "19222314178595352103850924050529785145335543594047256882477300628035520724", + }, + { + U: "6752616648453737243997484439092412728600579807726134625296748760101881695261", + RefX: "14372603587123084572842079026214385071915163797379048302285171064395091624319", + RefY: "16858046992787787563787238687483322384534161621528776428747719720658554634891", + }, + { + U: "402405396687422004172126462003527942170791966247798960339271628296336340871", + RefX: "5935847130709288198490991530327006582795442280742988443532061276969624338056", + RefY: "6067033625513648907010593218679237765217617615892687033014915834011486001579", + }, + { + U: "1315873379567222147169846639373799374682501774768596659731215426101627374879", + RefX: "18051480725177647554873943648106505999502062234438158127796937402194321655217", + RefY: "18627794403119745366336936095420004360583019689482774942261435386733723759925", + }, + { + U: "15739259643466953559659973705596604018806165975422259484479201057652680821148", + RefX: "21742473845639194427116757462863658832866591014036540157706649617967202345737", + RefY: "11959939585237496003820037030824258644886300604159899227300550200056989936528", + }, + { + U: "17999848865018385907638596571412948284104978781533453345805936982367798886903", + RefX: "15457143445400895790063085051448689229562965770171878627345558541308853880292", + RefY: "13783547562214139753122002431624874385456965767270874409201831127831037433087", + }, + { + U: "16744947017266105418810238780847261396198385291790084449821986521295055414205", + RefX: "8883441366048866532037916135001465366830727391262887675721954377903078694931", + RefY: "17284698370350120113085016184439003123215886123421977639243512999459207084243", + }, + { + U: "19761247014216803210014980879119647040671278718433001656855301045631159720868", + RefX: "18436536233360659708947256636904473622275084928990590023171324031262020262283", + RefY: "18239078978998223792526048454322766546586670231400312568383869112643022818596", + }, + { + U: "20686683826495321925131428599032157777559936184993581220444182576840803514627", + RefX: "4402036696131048633629113172260659780451196984283269664462205642849851558439", + RefY: "13392465503068477238559193299649344480065706025963366177967853878133624525201", + }, + { + U: "17958017345258847156027044187604768673460144774793734700656654300294215936394", + RefX: "21709582378043991470917097027827936758860926743961192775715938168658041814780", + RefY: "3960443677055096996824145847064960116927870295164568020342896236138326007604", + }, + { + U: "15827803794644096432054984004288750314865628064657925260444969031100993130648", + RefX: "1894390690296564673963257885924124942545833995867870414560275028336482421574", + RefY: "2681195770124975412542354686252098948248346049346340495317693107034906313444", + }, + { + U: "16846269900798433895197834917225766828391380740002317074039565832409053095027", + RefX: "1995288923432579029248856909190316696744675421364317138355794531262438175191", + RefY: "11726578800170288294198668218605915071723715709926187447170879184923456447591", + }, + { + U: "18643597743304395376220457303044474507889127433548818586006315589198567336295", + RefX: "7612755924890935620994567673777185889281089608650194640314771768719483912872", + RefY: "20253253765929322240594860150647479599206399524312285819431293399590945811049", + }, + { + U: "3193209468400379879384771622087700847930585607799800312128888211842829402533", + RefX: "2831001422408877901302202555760456178124551916188994759421199350180322866457", + RefY: "1474955681802389980926038212799742429472372690656562491062830882095954138889", + }, + { + U: "17823046129057166524439438073464725284829079374578428363633219238082310057091", + RefX: "7777423458354021610512476387192742392848227771816446952018143560973179044631", + RefY: "10847187621961479736571733717857775903517520242060438254933579151662794036093", + }, + { + U: "895298516949768905200869393735175560679884237274793958290907724597607997629", + RefX: "317630683727698803416156153388951838240838299687059830218987495240000058450", + RefY: "17090553677247474260418788395016880075053076587128644832099301802467001466835", + }, + { + U: "1691798905341287453180503830397918790377241606183455032749960419397160966832", + RefX: "8410287668887952486149399257608680026741946394732873826761296737564236776259", + RefY: "12682100102284434464216744561136605738737684107103979934685639360044140167376", + }, + { + U: "21517029577993499919479754267252133159613284652479472870082826493920587754837", + RefX: "8349340127183342873894648389078883926536780894893900541891972895724707042373", + RefY: "16914885489534513350763077511656793515370716706235741914653789020951336362369", + }, + { + U: "21765881885811827315196768115106925554788056252025358499024544354214729922653", + RefX: "20311554081102542933467456963485298967119194334976828353439765003412634655147", + RefY: "11284988545112367346703375002759452194632467399913887007048223701144259017343", + }, + { + U: "19722480504890559483921503747376184038675931803313337306651766908942585115812", + RefX: "10886893189935907241482878993780446342883050880557863243991531933512465064640", + RefY: "3340468443916399564732602316428715391683271746669453445590002273964067476526", + }, + { + U: "11970304876566651664513123426287106013703552601441625749222390962203825776661", + RefX: "12083742269008115275289709351019485971723881735345680995198798916728815988299", + RefY: "2922061840744277524082037539005978906314498362118826236405654052868677951935", + }, + { + U: "16222274890348840378879576949298155380948467829863096897500659356909049589140", + RefX: "8787159408023921904748489948503133470608502903760081783785945410769132254094", + RefY: "21560463239961409434747589297130589252734092741200876482315142695397335188346", + }, + { + U: "14910938553776330503193134336193616795673645394333179515667214552439381022487", + RefX: "10828134197880383956973877358424476396940493070875438662987799680291169498176", + RefY: "8624862245507433337688380743859412426578367013264514210854176402011613310299", + }, + { + U: "13305009850400510749033399819090222950062544065102079339741297952870031872064", + RefX: "588214743333087398625881524346442289833477774541774251177171236525253099347", + RefY: "16655450473319417338181409762165566649653643065750853679858264201059028979106", + }, + { + U: "2461630947070617081574581998407719482049247473330340573434375844541953675589", + RefX: "18690064771480838977604800302176695542931118889823924092019077425873670984027", + RefY: "166221980675877763999530361088464996384386310050545533412863766220364484453", + }, + { + U: "18878088646876572395066591683447817119109958494937515092976600552278144894322", + RefX: "10657348695551539937256902040810152860450516584073453829343112821043225419143", + RefY: "3622374725922895352929173156012181659138189859375002155252999981440900027832", + }, + { + U: "8101348958945863034627079864436307446470521809956831529641646829879737267399", + RefX: "8109131175871460391872219518610905973726223005028024796624394673925745871310", + RefY: "3185112871311962420662515071352831658524637407147597226021557687580598550963", + }, + { + U: "4693534533798608502136089911266721446243116733955302149215674661952385114273", + RefX: "17590912598533008196684162260549144588254357221309044461101968040398875083980", + RefY: "19341896685273046883896998441544805848888233875269289825859189747127061450853", + }, + { + U: "1114180745587046173746447545399879786312060580015992014728301869218299189223", + RefX: "271008438510249487352048591663508708889677689152229266130919247858294693119", + RefY: "14427401059907413036751532040149004411214108993310001656112768878633953634147", + }, + { + U: "3875109961889009662750851261392849521242661699242520297369161020955022961953", + RefX: "9078474721806379453632497583744387100215431324649193820878926721841609166369", + RefY: "12482329965956938659263164843372413707245025659045900693129251930053453100127", + }, + { + U: "13101760829862788412832307309440503416649684325708460338669059258635373570990", + RefX: "1895094401219425172338008552976904427282614770093495187213919900448423776717", + RefY: "9148761251443887263132144409092746648491905955272478889137508609265800276048", + }, + { + U: "15459686815323070261041704312526604725898597868443889472636295372492401979164", + RefX: "14221886265299017637382269621986575223138004564203295990562090994027057998453", + RefY: "6363617526161308231201894155092795670938786063317655402652465358744835277988", + }, + { + U: "18609130893819880305855676969037604982786791872448806085583270219292421526133", + RefX: "12150886304074635298526207235155473867194943914047321433794308813346883008078", + RefY: "9837315694801926084441941746299466074187885643463982441269278543464471391891", + }, + { + U: "8773220932847011215346412280641352495367991816746393844672198174510470204908", + RefX: "15088583747827249406945732958474800821841879798267244385431891417328717958907", + RefY: "16569155529729355638340620755757212732722999455413701445847344694389667659942", + }, + { + U: "9210725114376253864721053303980318746707618326196423977984351587734478009115", + RefX: "1040916500752355981457600617933920931893874068828078519984062228284830146865", + RefY: "12174121548922527031783787340575827263085341615176041742890721140081770909885", + }, + { + U: "12552530350243040459926072528722429558306181994369681421452916478771593782467", + RefX: "16079167141024798481733680578689248451147602737252020377983587685452747447796", + RefY: "18453802110566396383818069040745861757406087835171416173549612801459132742307", + }, + { + U: "2123047475516689494636690596764368227769868900569050908366518636738963002839", + RefX: "17642154405609748522463462263496179355164496896143196823036504181254702808353", + RefY: "16682356738175604527259076440025959925347109427476275134261732306960711161245", + }, + { + U: "21884026943711630244978388868049496876000345959763414126405616843352270170866", + RefX: "4120896067428786630641206734577781107525714391801874119465623835616848643896", + RefY: "4430701370293867735025824805176713171661844399447741128360428277698971538406", + }, + { + U: "7745011043608066202708833455705003818207422715164559745263653931465226918075", + RefX: "5987538719842956677171184506307786753602849029912895514804601032141773592633", + RefY: "21801111956807105658947293741653358971969812962740981714391561908010232132053", + }, + { + U: "17026538391663861354425255343352028967568961321528866348047746559453916816975", + RefX: "5547916361350044964230903638101728241809121529611234385208082549777486337871", + RefY: "19123278584773168142137568899242794170821660447047634324901655270870017348039", + }, + { + U: "13251180029000212271694934962763466472567369642987575689511090448004973356029", + RefX: "7788786766128322698608476064929453324561735733848902730738920077833502421910", + RefY: "17252332557638321026729259755228204906050685184151613093453931864348165569253", + }, + { + U: "21607456207006295322400252793203439437912388554838225464466861308240797262012", + RefX: "19993987585475819726329434176099822596653069765574981064285372954873523495294", + RefY: "6638276467619567682170186359876921132787679859831482922772863385529457817232", + }, + { + U: "13341741451328121448885511775644360001313746783252035302448499864691192976426", + RefX: "1365013352388651061230283571722768077181518634391432735183436560598473106111", + RefY: "3774495448357595921427093474635971325710736552232818350777496282943768638426", + }, + { + U: "11614049442033548143662787846545823337944308374962608281315296102095373899570", + RefX: "5164895587464189255183389611689830733838444111605010176349953177954422700096", + RefY: "20076166003426063578187235547261699971201505105935470098348506407137040633950", + }, + { + U: "11724986370363864567234882082006255190475603359233385682270019764713085206659", + RefX: "1452438352604181129863903833953978288051493036484928463923346062693456105852", + RefY: "16842064525161011897114977564096030693697554399245032461026404737064911864321", + }, + { + U: "8797272870012222254124381075937563523180026090217148010905230755930262540819", + RefX: "19229007217989374564125593233771619195161927708169220425546296694315204648231", + RefY: "4603331810169758714273049137060420117348027263196447353570202279395108834989", + }, + { + U: "14998304117493880384036652942756856379141074748241170438356760308299750135640", + RefX: "4199759832401007606526410200728028649656547829846395785859832246974948417519", + RefY: "2811546839971472155155759998138857668361068275923680505869462054594612504278", + }, + { + U: "9667187296639227001681583142412650801874662518879060689319801733076084547322", + RefX: "15461541459411245897915052494696388170308420796356964853057497518300681732447", + RefY: "13385541959019012425534763913154564458975452647608189920577719879066334418464", + }, + { + U: "15159392283319172423042108982716028459906029669665176908173639675052243090575", + RefX: "17493380237576229505165070573664970663059928013217308320176900475537502292991", + RefY: "14932124783935105291263550301331318974879409768966157857873064689946624939333", + }, + { + U: "15270686854709787580052895518875818804536884124891848005759990620917966506253", + RefX: "511366589523514768167022690016341186660204443639074144366532885695031160191", + RefY: "13555868949047056505443851872863138351274430297935287199023377171015884241523", + }, + { + U: "14191027924588146957702922242203350208810103708112191053204851057693848406584", + RefX: "10223218869960793337349980823052863381481233829646565528379862638027429630059", + RefY: "2576509711874894873273485827643337155082131436173666305994506538881669519418", + }, + { + U: "6154721192490885481457985950858492528682341977984247905636533766945309358433", + RefX: "2249424867380562908872065188087258509270288848452113738211668134574006962147", + RefY: "10751298035611747950189345745884466284826057106877296077489075413515093463795", + }, + { + U: "4116541214926251924610682830846948926250825038963144236500894663402776182194", + RefX: "6473495026391879344149744217717359588133710219911966684962394174302366210848", + RefY: "2666653463139080057925186702360510188704986954167992524694661183916581690830", + }, + { + U: "9662686591321831342160972631134750764701758334848295723175549300422098579761", + RefX: "10190684773150157924020820958339660790438692512994209279056529352858736924861", + RefY: "6307813748743892495520127303365489532234536164130237906800742598454629106867", + }, + { + U: "14654228157109413896382933504607691766207629187154952390715648796607961389512", + RefX: "16153200417285059851513880686650299196444082220040362160327897144443352592222", + RefY: "18266272994551272507657178459223801088982556397493798620754665175239242672248", + }, + { + U: "16425356730399991413527933741371029276817634359934787063204572583130993436958", + RefX: "363613060899361811634638513797918138655546180159133554045030277958272201893", + RefY: "21121207867689034800054011230553598452090244116015983653234949420226856324304", + }, + { + U: "15296513543471217485172735336298072932752405486038197201325985479126450973272", + RefX: "8546973483910583290297189176547405688377991746605991270606263485494779965921", + RefY: "9714108909680901168140603523162949368563740601340438191518668345987904102680", + }, + { + U: "9769162994759035750799863587152227410770425107588411798099520447031026460145", + RefX: "11425776402130929671532960121727376995800511959257342038775060809029892235044", + RefY: "21665594817729995314938814087160104529598197435539181863570548491128736204901", + }, + { + U: "562652497759658797602811636606989173713897894739131439517073913062677917229", + RefX: "4549062559785752615604834867545403111683933068173244069346468792589042697527", + RefY: "14846090522092148580536394343299764678244828779133790848566089823800390422895", + }, + { + U: "19827929247318238962686842121546088901049955479057676209279532772083324575993", + RefX: "11370970102372506905834194812745823548792465195861339676447502100412112643848", + RefY: "20795929000655352772417574442046522305557030137017013928021171080580382542475", + }, + { + U: "7056825023054418211948938566972116534319115703661444487175780829824936159308", + RefX: "5711880571881265850302392893933473341454328750818250401471826398787938229515", + RefY: "8816440849620765174850722596792251489882240963697697675125430231986602131166", + }, + { + U: "20366730182523270650728933326406347608341534658997059562069068134068929326683", + RefX: "17701330583353334677378158316457646055416512235826702977165167823015416161477", + RefY: "9987745606090621386869807613701981810751778142998980795922293550091597955893", + }, + { + U: "21090136589288072492547717258757704056395095072317955794181642698140372600345", + RefX: "11633783597844904262930196028373316218374750818614856473797512836284812122647", + RefY: "4114709087379979383874359509968559396710474642025483564971157486076278266091", + }, + { + U: "14166742176335477407159652728556555130400493567752055087569382180060511713494", + RefX: "13531400102498939846996136250858546893494430846855928037900047077169462649675", + RefY: "14231297084942499703626464562821378733544201214212312459412559915215660185736", + }, + { + U: "7108156769413064714483452047406827839852916924070743883356283762172317232216", + RefX: "14619169540251822800960024856554191212052517436293844947930368995424580061462", + RefY: "14658889735618461527838890327255132063011987627605716314588945329196158523686", + }, + { + U: "13909026964542318396205867637677042911971962368561382066939844138492499985196", + RefX: "13117973730940204940585287172245098617013090150931150689153547446159231960184", + RefY: "8663983632411463526323199993642655341330138519867601907870149898429351245102", + }, + { + U: "16215021618745106615159946512245452983321819501937588571435199016446185096212", + RefX: "16017776720109667483855233839146841664001677611551526356408350212207485554293", + RefY: "8972097410466985346587724865734855939625673339616430076662182532922213813328", + }, + { + U: "718039807786288599850183504380054819506753988833074835083254668811697456963", + RefX: "4290633867501154917481143964133248532369340556639504192972442156243676259593", + RefY: "18155334243716364493667792867477269209268498174109168721110609798943069336361", + }, + { + U: "14107222590220531546883875171084468895678317650579554861129019700883586880327", + RefX: "5042395571788189219608827610697688813987185249565663510360349993525227261512", + RefY: "4267592665200203916672946375502146130554343765576792974223844040068299135789", + }, + { + U: "17474175688499376387828624460104120747520951856523242925003996421839089460320", + RefX: "13109254459142557270444718377072489258404559297758607048078573794392552530723", + RefY: "10562118754153669335569253697434745713247560276310615786263528863623261655422", + }, + { + U: "1841491343650171865201846590344164396371959313628645907287043163762471320199", + RefX: "19793295661210347341295913265618758690462560848297940601611483585040768576973", + RefY: "8637953169160117401483456498692606237526361184901016160763921414208739783939", + }, + { + U: "10496586509147072136633310417416001854940921887739513794862918997776129850143", + RefX: "2565170237114751469707597481581942972575251674912576243533969891211073340532", + RefY: "20148775236741774422453314311755214086985877629106705147390238843337419479041", + }, + { + U: "722414464785087542817100385617301545004496069036427619113895190885718576587", + RefX: "12728399874356428908271328009380059050419293292535286181068098865927603868698", + RefY: "13772994063999230407135657399272633040870372085883397775427635614855715616749", + }, + { + U: "9672693103890078846111642946492566874620179939563211124512206302919465517629", + RefX: "20258317783540410326928085483654264501101016841718380727175566579158051509014", + RefY: "3764027810165224306959431303495323112198235515430103464628323227989699409059", + }, + { + U: "13726336375823923322557394147876759257006633170721237700591879120199933501751", + RefX: "15092082192428510252768525925881784511822043023563112543545219822541054777339", + RefY: "3353134518997073531714413245323080153890386489408253258210549167748460446103", + }, + { + U: "5531582948188033100734720944029822063015411326563175179113397543177730560164", + RefX: "21232074806446889142426716450577370712201565799005138748983696543624281124640", + RefY: "3627496697807383717369424129392574914826437973010560006089088034293862120460", + }, + { + U: "1644599558681795216611982246975898576923594062634231923359614326142147354751", + RefX: "10751627330864347902590365563433852330804912016554588316271183959973478280844", + RefY: "16454518902419483986316927009760058598349244902386850937324376433420112352371", + }, + { + U: "7093823638969086931254288507042204741633363838141319355808186888002525390630", + RefX: "6244893893451703209039836618215901137616596421348754869238994509150974464375", + RefY: "11573219979564687180956434691166864342466209682517768995335492118202687294920", + }, + { + U: "6863758272541655245424963083975661054098084127095675363974356066884308990589", + RefX: "9165295972278333419409336491980835156409846378999834590467541653906737560212", + RefY: "2839282891077830247004673847972045442863612561003329640662235594940351871019", + }, + { + U: "20723725934157726856182484272113027289268352684297363906581711909287847351053", + RefX: "13694124469447905191131520552383902237562882873350509181459884745395432486634", + RefY: "15389723301904662181103645637540308535864321343397676793833065728220726380207", + }, + { + U: "18630114339210644721520905735317666844139174873495633718324611912392684413936", + RefX: "10309509847231509090051293687963351347594431496508070998992608861238248541072", + RefY: "9872546386316605659585168274263479709238424332482476951133504758150533945986", + }, + { + U: "706497529378652903955134291743445209343112650139330990320013709275056249047", + RefX: "11632160340543178075232648310456126663806872973173656550594801582260075240482", + RefY: "5498063443426990938114613395049607487107914768277509606550081529091347966961", + }, + { + U: "14773795604821793990921412814743451454551165154075201204186948837220823812084", + RefX: "10288183862330674546090052704776549783379535401606128362621008451761400885021", + RefY: "6384399679322845895475595618995928608587340647528833837819432689146428553878", + }, + { + U: "20974317055644499578665816640553800082325843485313944906869050012311419484683", + RefX: "10536905299207738320965635632236548551540433624985148681470067253779479441170", + RefY: "11575231570330510392807489134663072636955892084653382773369798154403134028103", + }, + { + U: "20591482576250587526980538141435465931115154898437473714159350095151964116891", + RefX: "4369773664345568215158420405117505253750716844534532146107828509254267812947", + RefY: "13760604437008614461214554954231838801376695502533786151108361480011250300223", + }, + { + U: "4201868981281350931047562079070714033648375939933290472551648684123748791106", + RefX: "11418139853010513343448831468409091394508106406870341453172657646273164433881", + RefY: "4207980748714174989371957438512004171629302146360918718121182502656047380374", + }, + { + U: "15020948940203966684841385248544982559012567901315447205142000888526261886115", + RefX: "10854915540065483758911134820267098741845069598028541913697575146318539760165", + RefY: "521331543543431880563799006526355653538220021800814429551151311304185171201", + }, + { + U: "12645051058889057992795125883860438877412376942788717237331153181544372555390", + RefX: "10292828728109772343621389172574370364160449207853727628580318209475621017753", + RefY: "5917867370099293798192186400339334554553517982372284855477290580591911207418", + }, + { + U: "20101837888704051096882006309240970231817552803848739967623337238495247561480", + RefX: "2166041136894170395153361549652602227327740886546128123859728291725807007698", + RefY: "10883869735639751631889355450075441083095589350107596548771830122346530831312", + }, + { + U: "307623246283381133503642812263764520159526126306973817771918925299279734736", + RefX: "14843502050991858664172547413555927778116743703032596655805137295325246480334", + RefY: "99391493727643477765810262220093582073817279295996577500270724710024017148", + }, + { + U: "6864477623104855714356370063644952564361800923582921822439648469991194388628", + RefX: "7166403114578901888766590270207950725649007220334826442783778441789998990392", + RefY: "15805683788801523481220661924388957635411777802641863599576484344256248584364", + }, + { + U: "10730254671285392893251459309749746728474892949961087008475480861015688207382", + RefX: "10231311973648771799534856410385986078459368450579546325071110920460201302771", + RefY: "5517035372002348060730688668477033469333372507796354477999566138751360903206", + }, + { + U: "8881867294692454798298657948138008124263232600070612233680732672094148914117", + RefX: "5310263487410291279521932556406791926535613187842576689496999916642998749697", + RefY: "6138570010306635271069068766524005260246988048062939060046909833579158328771", + }, + { + U: "17723873439819606306683949773593885880973346623716843880280624679068623267666", + RefX: "16818707662630949618569435479909197045046105046024629304688481388187961759609", + RefY: "9077086725542250839819812968319808880279523150689676733253005798132859031354", + }, + { + U: "17811332708358512211193634583114404981597052067583477624368259100424577200553", + RefX: "19469391782159752719429553772462935732694420069272747889945177590468432033418", + RefY: "19772924883494532552889809392136285880070797121179787229120607122379903100217", + }, + { + U: "17578052971923750897096145564140014868169819483422174923261237908281230173468", + RefX: "15583859518586718708239234915689860693783413060743928916252731394488038508363", + RefY: "6437296277455398489959523185498809369282878315768655787215458692089497312054", + }, + { + U: "14566225243876818146018431312491058942996706132389717696338085329803753661057", + RefX: "4660274015797793530507894112067234995238276967077859719433952774088729918907", + RefY: "16431175220882753005749147628222077425632626388209516116471579290809583900605", + }, + { + U: "21437181444317612401528652356468666547133204742538847144923253996315524545421", + RefX: "6658770631801818656313126244927285723915749860331286593785321256934043873587", + RefY: "20423928469020225519596468504301012022304401600048171977915800026681861110197", + }, + { + U: "14091250780202513250251926934565166725128141860718807714140433315360444059520", + RefX: "21666478425366982235046920261786980622280445737962617089729105667648836711019", + RefY: "18727337066382333289165554603347963058646133167734481395526325480068846072300", + }, + { + U: "6387926735143753917453021217294547776350936909417260778683387872649207790140", + RefX: "14982011040980887939187999086277284072849009854555505739288468536343934013680", + RefY: "17421166454368812490528504473666052926103192106042235745654584134568721945350", + }, + { + U: "20887900199826641903126451878391732646215421877609779634869725784408880575964", + RefX: "9260135071117996600633270133594887784839704754818665631065992252664603884100", + RefY: "20165733909297534242402993315111250870092292138085784480622861444810423160024", + }, + { + U: "958158669350469263435757802757999271278836191934249039762963316432655989759", + RefX: "8945113583680954117336244909143930728703186988757105760657200348960999791553", + RefY: "5679425312898607357369730340088657886854671524855764284308323909176938313385", + }, + { + U: "16164387294458780978800901495816670829466005928056514422804547778388138362294", + RefX: "120707898154043076525437418372960619573986391687562715654687771856239956352", + RefY: "3834706516433889030350827458659103598891204256207266220414361296138692246770", + }, + { + U: "20106982504616018960440220207216621868603912809395957109973803456654118322838", + RefX: "12499228336436789218970558869108861727731291282462545878085068361245189600537", + RefY: "1873761774408936113537745747702806128063641759288861413115928560706820749270", + }, + { + U: "7992159253531161510010806284517359393626737568484417224871546385532214108479", + RefX: "1607200650407426669474360312678844210723825139290918054993009649707036676438", + RefY: "10092507359047839480864563173540666207881199514725924740049964567354464544893", + }, + { + U: "21379697026872472251310337981118074285223387885355044632353491093137854144574", + RefX: "3291993595813530483026049238178455514739439545092267013667422935980954011414", + RefY: "1054750708119592610545889291413082091746112434144259493798491922567700105852", + }, + { + U: "3652575237861447131952337637570076985038489928556348311161032247885922206919", + RefX: "17450928462614841637788856328182919121948374493077898036519338703493895787908", + RefY: "11689775354891051431210761336820975676023417262062761177869984632772472315589", + }, + { + U: "17962921817189304745450674312746195401724416728881606777939315570851226041575", + RefX: "10304769147871525843137660027516290550262341804656656084766847584320722399838", + RefY: "473801127621060381349172839795516151485695097208911888473423339043641769725", + }, + { + U: "2050701943878764242900382307182452663812018941055162675520419877329690349386", + RefX: "10118471817239700245047025192193583119146867513263122599272260812260408546631", + RefY: "14301235104093417163747429422673652606261572628296487664922013550439961891004", + }, + { + U: "18276185234980690152306948255831386291077207529286760691120246458731023392711", + RefX: "15513547084174944717026455637888256160446345892203457199732498273686672054627", + RefY: "19111438750066230177664126495767092516364520846670849876649513577780700049199", + }, + { + U: "7988521437096626087136272550157491964072527264074639610191218909786135562982", + RefX: "16405820364467873465942639398047817230148847550240095991132960077170867469666", + RefY: "7097692697234707076624300591175791818735288139807497833166602409622827425910", + }, + { + U: "10691073339316444245230239082580570864024268910693381416763127555841259070468", + RefX: "13234829694327023978517379099635993185227214574234981491548587883511129597721", + RefY: "6762922213177616520657804667332107092860357061703206010703685811966395365494", + }, + { + U: "3442909789356558801638195362771457027937669984716827452908876203818336869607", + RefX: "861373850802256142489085485972455502295426095408459158586846608723716221437", + RefY: "9064328282557644620450747968861888279228024470265551809395703407832797435597", + }, + { + U: "6626409789222268283227234296071964859382647371222158655704369445791331240530", + RefX: "18584375125172892043611330416353059668180648238499517932438884274123767975095", + RefY: "7618225694986225637813099683883309747813363852692694974064659239254194616618", + }, + { + U: "16843961016065337655296023054187903236080887820616774705611354202887321647648", + RefX: "16795527574223041405809494173223488323938771580531325701331223737607317846252", + RefY: "13493864655777250278544206086858257092873382915945466429732831916349823782654", + }, + { + U: "13398545858172607765255146399345940345114718211642717483348707252608830656610", + RefX: "1310145946568999377572661680241909902824961889552203235461686018039629979509", + RefY: "19564423897820858425764319000163411959848206443657377829536300146699520085348", + }, + { + U: "14086990595358360148810065347283842150741703351733480469562258198457241993141", + RefX: "15559463576707872817099655910143958232306925832161524508653804082247248414203", + RefY: "8829630300393901236192501348865483550005370044413523941889059619851456273013", + }, + { + U: "17308142872525087154388955138727050202373057147640565842402785746730886271960", + RefX: "889198039535273699581274850479819188424384429695046270696842504291424082076", + RefY: "2817548233399595473573676909674093625959578011541652638857445905062095813180", + }, + { + U: "11467619282696967516400226402230777172745794732642069830578203170434098291839", + RefX: "12168563303004143888298137661941064248184569486098969997447171834121233607659", + RefY: "385725733042311871702359842372639771434091559389616087208821884536380901393", + }, + { + U: "15760996398013210390026015988283826822274679731176761289391459843417523695626", + RefX: "2390309487663955866935774740806862302698096849868822368628912022288921542538", + RefY: "16267305827872972409994980090270688259158642088028280990514671037437901839530", + }, + { + U: "20895766468047542014228347259245350306446657713283165880633046865530534269957", + RefX: "15176859531974970800074477656437317527707384913521986532315451594987735406516", + RefY: "2980851305290338235102304312897068797291386072048464482399002276290113910895", + }, + { + U: "12327182074002122247527051369885911522355427023761304443323567367853452333271", + RefX: "9765588638462800003867922187575387198909192944528014471631459013474864182582", + RefY: "3719943146297087762611240829923746857431119639354167456241324294869757596593", + }, + { + U: "3277227140146304730274844624975872258156470782787351853569153476006195676925", + RefX: "13147055331122550628405768994692660194389305812113139163293112829952294600905", + RefY: "21637033366973475976853130593743010524325260128837252258936702951106726741591", + }, + { + U: "10109002594513810489578506303966542107759798200427615746524631279811299758879", + RefX: "6454304505564902739190447212217106319197271657765177733066023731491139611414", + RefY: "4865805852906616257883984969714498009315268660279619396266822386422593666583", + }, + { + U: "3267278511757856282453336205087612882198054142898021386394079642169255184589", + RefX: "10218538568159601457422332811206090543183364962342999893224535416600679223175", + RefY: "20266401543658936157691954235081808452608588182644385652557681915334218373541", + }, + { + U: "16864496704907308286387428593408684704414910980240821837290514993455359424365", + RefX: "20544084566976247424502324373202718784665478472247032399591568592348293244324", + RefY: "8088347779405203707592121720304035791977989694104243100341340640295085226273", + }, + { + U: "4020293300827774285495154724659558827534474437962330786718492387679006533624", + RefX: "3996517132818924868267026646181900964119851170884041030429968759847956928317", + RefY: "8433966870230070289691802332512357963130715220516996927915289645135479743688", + }, + { + U: "4573982152792479168004844120389585222152949519661135772343810005043442866094", + RefX: "17670002952296027476428592556890444085332444888980190934298330959457139426298", + RefY: "1492948729117640316506670397980855909294302085280327260864078237630360752290", + }, + { + U: "15357228036335251994829581828232636186115316077351838218040039576800983271692", + RefX: "5455829109773694144516741532787460401852125606712229104500935844977256104906", + RefY: "5562298296977791628312126144524415212964964173625943306529550901612950138368", + }, + { + U: "15020002126359754270774368594757275661273543070069712629280900927763929078045", + RefX: "11030744869389929961250148449877637603552602666907205411220755485970787335261", + RefY: "5644340528276356123153229891133833599868332516660518552725104780529293268359", + }, + { + U: "14710263259892193679272944800583110686322910254847944695745248956715376480474", + RefX: "13378511057291179654038804950438334289625866210454599900967444456506465179242", + RefY: "13607359419795669652466533510574753398298965708742353883493709614994075492908", + }, + { + U: "17302683171625292679832543622921969202381488745409694439100684777704329133989", + RefX: "288765452943343128093708249269013416616251457421725771389226743988937435799", + RefY: "8098392264777165282193343747345194133877576069668375724755690069486568039759", + }, + { + U: "9884044417592906541377797296229747018781479708688772783061518673219865723353", + RefX: "3867140656091269347451296357567782283835873009106183245180203687581921309175", + RefY: "14653060297294022995354113387200282792566677573645615397800997453165121433907", + }, + { + U: "1273012232613478134780150717199105500292943624831028438095892797120054211422", + RefX: "15495965296056782877779948811438879926624154930998513139922168732251952011001", + RefY: "10404317015139364400127241644520095592879786612136589099752058733960919869038", + }, + { + U: "14292919551574034716626149552870093464669086416752554273118871471539900605776", + RefX: "21837534852796984004180923469424959918926719235592247573842345537296450801382", + RefY: "14897164431208705158572775001431217262853959022923493655920460847982118245168", + }, + { + U: "4327737182542574209365416205913405076920211444357650637369997895591553906067", + RefX: "21023913861085896103581397785748990286764917180302033463241200582512262716665", + RefY: "1472230021151532015042683393405147593057749860457769364648245936122527401107", + }, + { + U: "11555690948811438960204087772481744800850763401686889168751353051379237048396", + RefX: "5921052674911900376901219910207042896358167903570198674512524727996662747663", + RefY: "8353374570775652045348921217891232614004186277013117061453911924958063530348", + }, + { + U: "8066429796898539916675334591892381649333761166330689672900912694280557048321", + RefX: "21846799299505314111615231327497602672559018746539073520205448360046465337738", + RefY: "728460456737407675059194774240309912362690356689381625976150306147718858017", + }, + { + U: "3336873104098027033123672618541333275848022601355288797283932723626393534763", + RefX: "7720358756549876116309376762272725859639295611503445332014441985308798697520", + RefY: "7140896007474556104511347112367045064421978729552701768565782416517817439975", + }, + { + U: "16879289531196343956176863912740649528801538339698512248901034962805636749909", + RefX: "11417775678641258107835224740841971664420189530542429174548107941630669140061", + RefY: "20794486411463770779704680461548928143480211855574697803371290321095942104019", + }, + { + U: "7995765678857662498752947006669883577267661916899865555441515414928533813737", + RefX: "18253945095058244256937258655449769411747446668048521355856003935242146986700", + RefY: "14750718491736992198536098544015927045468568460225926603673809593463787734499", + }, + { + U: "11257473283069504230169246892375884842218964841706489242187690187395729295662", + RefX: "1359111584198148208465749225218414737965629253488296273180889186403460679634", + RefY: "17623023457497067986122417188599661268382747719347427419586457479250193268654", + }, + { + U: "8989003270660303671236571421269373441478063068988115988064222674926090714082", + RefX: "20112581076269725387766161349388568679349777259248324926562519979456960300034", + RefY: "6784700345598935204609582784772034091368735958516608964725841977018336916496", + }, + { + U: "18710359109322511055652631961849279663601567621445792087101379352626014639633", + RefX: "15736504431293724092100772515312567000686179858064434923186958671823136682602", + RefY: "1603978854040931629673923843446473383691671359226291885813517978579869179557", + }, + { + U: "1611723348833058292217243000583717854990700711243162272577615510082949510831", + RefX: "13601511797216153369178944990186469149866810035387393353442134295548481427155", + RefY: "18685033749329418583970023474848323020041807117993464763616840680645873286863", + }, + { + U: "5370983733852243440738262183596262657030691147028459612269407304826691793667", + RefX: "4123955856040144226349334334575034333897901087701899682194191234346231129387", + RefY: "9917742181948293354217330302546051435046399023433311011387182028212361535235", + }, + { + U: "2327650810164643979810359194929578492469529060162546025692886132973571361575", + RefX: "14746795619872803506860370846050541232443508074562739397184274091203041162442", + RefY: "19482834623735042143731278828299758138249495817366538017400051549364783134201", + }, + { + U: "13699883815802695427086822629383029245730989289646222385666929904967844463542", + RefX: "5521421760566955399433069159452538913288069615832573364833987889053513958557", + RefY: "8251929056142207581544589590200512180218729249186470099178691920246621199000", + }, + { + U: "14277094800561809907115889244886688926577906568274185497009294412934816669545", + RefX: "13026674024191212939221199590227596742659934138538963672359852988648777475519", + RefY: "10409685179012889549814667385962293987247649754545814597443031736480800106857", + }, + { + U: "14610526231977859612238294400258579277050600722800888132574902027112232221256", + RefX: "8004629379342776278270573658509275369952594969208594994174930074680091263867", + RefY: "6314405491083122065764194831126967731302921583982960616125442365993516961378", + }, + { + U: "18041643110983816481459725617801379127453315376639794364385330752022019129814", + RefX: "5330350641584524928665855062492056492782868901854672272037232664274122641640", + RefY: "20987995754805646879440429467850203591962747424353314435667364726777882195846", + }, + { + U: "13938494399681523327294260161327224939486108989236054408062024306807492013522", + RefX: "21686174522256099276998603190550340783767787581226798177177330318111392986703", + RefY: "1559413949973560244879613789533812580178978115655761594636770325913253341778", + }, + { + U: "20613753210875218476777609752368170406655519531151642441476250523314672685460", + RefX: "18203016144167617916333283600332612533990317461582937888610742968193599911564", + RefY: "21515306269613776810637448291572401786330289770529455316939455717299365936172", + }, + { + U: "6712698331467223685920573349461867331295914794610038237460131351682697652656", + RefX: "8823710344672719945330465255583013412765191144861820964351582264592955648702", + RefY: "20843050712594691264088311053292173650000276284005840189163572501725185559546", + }, + { + U: "17644648651248324534929397032050037693298028809677048850162059749651541974601", + RefX: "11329528602190755341258221338312096374733437475711112272338606165841249380871", + RefY: "21443647088144612268035274385547955930073554479389630472917380807543300984861", + }, + { + U: "10285608513767763831728950995891636600775783774766565928240227323767197499044", + RefX: "5955700415654118327674895600080307658170179715255953812441699466340704135224", + RefY: "3794746487344204779557858778967633120293397774757049533841593225601597446092", + }, + { + U: "18325081248802760030646625657462940925654169079052385269717968455140538906791", + RefX: "9146786104764367592244597916186871219972357928376915158329233493894725455367", + RefY: "4735759022147440777675015998744891628908263689559958788743629971938715529975", + }, + { + U: "11664264651310378473584275246443079655382964957928571760182492174983705805795", + RefX: "12164636205804120378473791262600228393816220866774161404175043566693806836013", + RefY: "18159288589779114253714479343172702697503160290910414344178758602771291718893", + }, + { + U: "17168924107731620583974804547118083418906319153308394555863190255954544249544", + RefX: "11196118937179210467470144888808458521739114055480646761916830048731722713635", + RefY: "19179318631824965050794293346660152748005803354083302275709777537436203044438", + }, + { + U: "21236722014726520164023381634776348105961966704938968185260868145131054247649", + RefX: "9184425388418037898241975671085790709773825318511811105072355740092375334069", + RefY: "16825038473129091098118588258728829482514826443742505717627135584649199088207", + }, + { + U: "20663007358570816387041251301061869137614837342944719922396870887876779839339", + RefX: "9151683016747958749365473806901065169201945286067861566469595335331438771862", + RefY: "4527475058732071758565761408907013759301222336627051553494608018209026835481", + }, + { + U: "15197809905069369640195158203232088495886718848241266981768586298697882407493", + RefX: "6288677370998306205107499557259615544283066176989960798604720435474204042915", + RefY: "7505387590735770933647716225817006723746339606668252240172297254277156061405", + }, + { + U: "5663062182331572149180888166676079920350530360328830729936902255944239177634", + RefX: "19003116001053601767971199216229452278930212107010051591478331881089949656665", + RefY: "1756533511847826422590697014141138875686095378793337741533932910265859065072", + }, + { + U: "19843056687419866381431468748421449434328533856551815675996708335111062219082", + RefX: "9450052021319850494996010668709222906493868751550311868062774505510994830932", + RefY: "9964370593843845161392111168489668335504829199145079895903272992997342049008", + }, + { + U: "7735712633967882791579011347257403713658732291512929781187878009986711084810", + RefX: "9381205579581622456734532688599274670590588341235185841215635494927454909885", + RefY: "21823421523275002016451715236010391316411992493003643550873248891033926425970", + }, + { + U: "2581552042528174245750752009385335754343670282323450116347045939784656342036", + RefX: "674938973836743312435423642785339685895809547906624526893998930195068757144", + RefY: "2249218522966414422219165176034385935548820894834975897884960616927114907654", + }, + { + U: "7848173592368321831387473192779106915813194196338498669055869248209341479522", + RefX: "10695843021529657053321740947898831128183252084595848057952608481258226734341", + RefY: "11575900705389397837919841190693966211851224378987105046454128526842376640920", + }, + { + U: "13211309849126697263598595727150424626595901632226271993489638271796438312885", + RefX: "18972169407533462212399841736530620979537938883018281382048035405799827005907", + RefY: "14791239378677917968741879338685637063762520977179706660322243590181604802403", + }, + { + U: "7104952017600636815009250208639436418059745999647809791375758280406104458600", + RefX: "5337645568742610202437519171031494960567187876738425798399447788766349578511", + RefY: "3887743682065016374141768163551363742735751985989755101205510812616919805300", + }, + { + U: "21540248838984284828547745479455558208879394623875616602355406686549391143308", + RefX: "202030128776912780344522183592653521053161407217810329163675809226385760315", + RefY: "14891053702640939615917253439542909927752935248948722917216384307030539017238", + }, + { + U: "16690173114698232391790144587108379388189469367671781312226437849213997338214", + RefX: "20761033183806282888929076208301116773567693555190989084322913728605554655725", + RefY: "13181648638847914066264278230649971746051167873217902225541743863508549870814", + }, + { + U: "3105739217004518805426167513052883324516249804835963563263907164632244326308", + RefX: "8321840663837703236330358149506872110114135702582709670312868476012564495727", + RefY: "16343435508102904828163809729775506357504278175016581691628581998460190277686", + }, + { + U: "14114604122400692503255218769352289415165846175649847643667851769181395332750", + RefX: "11324627476260404588931131936040178705531570157549204783595076753871262311026", + RefY: "10557355172880262416842263774219911953501493730387247683913431408665171012832", + }, + { + U: "16095850787904460017336591400664770756466113757996280427597200770551912562276", + RefX: "2012737399318460576900128268319931315957411386048341396624183662553635788905", + RefY: "20756678747725272934257387418737549302311941546357223989654850129814127718322", + }, + { + U: "14244333794494052593095604396062058800165950795561246201087186106091168897403", + RefX: "14483162996205810544054229306527030794849203989315629969380125253032021926262", + RefY: "2205291013253956482866846726308429426854111556918361382304582180114209581353", + }, + { + U: "1173935313974973819589511163581558403082161235110050035467746356143540715931", + RefX: "19845634228619479633641448813937488480043550802356101492323998926659318746888", + RefY: "19774613384949807357511638606005509257829270280151197614437795796197032912957", + }, + { + U: "13865448618859871534180873438417441249527430441944858121162004013671316121469", + RefX: "11890179549135805618441208647683360168840555835985249328689567256496463623952", + RefY: "3700889449217753496087044790339797212726797540095265677147641120526637334589", + }, + { + U: "10524601066693961082551873450342524539902142601548842649592909535545110713940", + RefX: "19694556404883000774995722051315113893286510333789197209455458165931191584922", + RefY: "21875760115110420103706820449714100088016353648472638483632963080074144649446", + }, + { + U: "3277571242055838657394421484747637107503657017732739063150950722002257502254", + RefX: "3519077227596750448594859020525028390397256512214998790148385909619785231508", + RefY: "14963667476088594792239079956955880080424547351072522599545755101111363113414", + }, + { + U: "88762887402180703111925747717129640533133764113553770929966163627698060501", + RefX: "15664184374274994991263826336575090140724550397380412219184589917377813210423", + RefY: "12242708559831259238584976240880768949741780304034454764891595967247497873811", + }, + { + U: "21649844210088949824924811672823075811474084992996797562392601204975681355073", + RefX: "12434905713910448597997908345232425000398769268819215910692755395477155530999", + RefY: "19625865200913109796229661834749187487265862238719930596305332181411326918395", + }, + { + U: "13204726383037326861127937646732367576356285819020876293201214704929049942391", + RefX: "3515305309017824971636982954172612046358302876026667447032231056289069631276", + RefY: "15350867237418298695241545690225738900663208440971388840023122363951866820995", + }, + { + U: "18142883377322206873827598361352999456759450864642769304696629759346534248234", + RefX: "16602398457793865120158540445432748441450775612183327024765288623842184737489", + RefY: "3299798026379356152937164856475104380397211999629538469045904576246250558800", + }, + { + U: "11000159866902830247703410521315721078352369570767023274355982809164104556681", + RefX: "8578765682913671061480861153362317574318040695053907793666376731623048307069", + RefY: "2640241369699538601756508202925588363193686414541410518191954726938929512923", + }, + { + U: "2388770711142967971176753523870896179944186804566716590178445796069214281672", + RefX: "5690438798722060207821577859562359146468036461512261406802605138115868629666", + RefY: "2964768644968394821526874219803449501657346908482199454637658929435435813832", + }, + { + U: "410986808814066268603504885442526485857257287487851784777009436022371752156", + RefX: "15640024471162248434466815278556606701391046006940165521719383415428735593884", + RefY: "6297768337601479207923038541712872244915586390597332049213358314095914378654", + }, + { + U: "3273445492890084982058757798244846562640401728896310890204788840213775736963", + RefX: "5567791562285745481022933532234923374638332187221242880893893393675006821325", + RefY: "16445232487491145273807191082898744156100546236551527496837516103317503862427", + }, + { + U: "16723695802685340524295527983351257878218396979101845018779944144180469629584", + RefX: "941249359206430595500089646179874146478017488943991325417392900526248189138", + RefY: "16861635722309701274577602984852271157486643824416799384084103747141104425294", + }, + { + U: "2263400129329963766185354802227474663080272886508720582730273425534765151774", + RefX: "6599972672286123830268392157348828792015679517560904023528095557305679017646", + RefY: "6967295464061981951118606944631940014434719858869371075322151020704371254074", + }, + { + U: "20905877272033332283636984205658762594744762309595982719908398527299756583873", + RefX: "545005083187064539334294048353160412572072005483623975881901821940499059788", + RefY: "10396894324256841187806666713837474482762760177935293674251469212492257459039", + }, + { + U: "17447020040830380594623135111881465068020763597477659694840994641153373102063", + RefX: "17317978998234328148321126130308409121694893860769676086926214716047580362595", + RefY: "5596773242560463795689109264016387258138929294786190778515556404077415021755", + }, + { + U: "5145162894893102815841644533218875232548851373603298548172324523237293399319", + RefX: "11342791123349637940850114300194699588794751939321432413186543505339033709949", + RefY: "19429017762990978110923190532656319835779040809288152365017311177177143042187", + }, + { + U: "2577508104073514847972450345904220209153468407176392317824972760656055575667", + RefX: "6831084165404310266917955884841395459934156505777950573747579183088121816893", + RefY: "3961534293460767444738083990191715259458978810092184278415145244434861565637", + }, + { + U: "2497112817042786560564061729479308208210783159204802068843220498624361865993", + RefX: "6151476171942100844560955038704956387478100671386240345383011578174390846965", + RefY: "21257913003223814953891549578927730652624223737350262016784958688736873578887", + }, + { + U: "16282676507954220989615222628034416267507221731302143719558176884060281482411", + RefX: "8525573750411715443655481164100741469026475756807653495807537160849772698364", + RefY: "20991288584501647719593888646341750039138552666527121802490759958100289207603", + }, + { + U: "18127101349858199346103653460183773957195877317047882915271477348763076308040", + RefX: "823510645134639244457516244085583732578543564095627282962969336838593660164", + RefY: "20126982535433540428603519361232915945974794720655725836639209132990675394348", + }, + { + U: "19094971477989308020786004207580665755875426681796944367226448633599192751905", + RefX: "9023372328928213753599200595447352994074616621195683155088427126031825850254", + RefY: "20206745165522695876306759400582387892924891251241995402537104529862601872013", + }, + { + U: "1991088565782968652051881683583672444160455335423622736811171449460052866884", + RefX: "20383947991180583496702713542831399692456886444858402127695030543318028485292", + RefY: "2107268770494280088041662073045776250661257489653696752449320819644205706802", + }, + { + U: "16146978392410423979472101348841198830023898383493670299937451344865085189975", + RefX: "14909774317458574964469815586818663047290531637145155768645570358134158048738", + RefY: "12174124591238090704495477022196429937977830466587755289707691032019453077301", + }, + { + U: "9066524988538366832619340388540916191681055859194008885433035323687840222959", + RefX: "15819149917275598350705275347441480403247874416668082717073099834389314133928", + RefY: "18941513448272089590932774731249051992245389977406902338564550030227328680477", + }, + { + U: "3510626760051738631205772661667326190072603298321227709811728162865314620091", + RefX: "6449029785573890890289613159950049932007258422931597824343125279786507967372", + RefY: "9218589843868709362054545727081954783422985390277319642568823052346512322861", + }, + { + U: "17807955911976135571377692732241840898588022136017574469544811451795820997974", + RefX: "5594373817478451384048080019268439173481832197225492674488860610892946108312", + RefY: "18754890754947544651933684172400205677641604870206060620707587383798098801120", + }, + { + U: "11652562520132466951508274144110724083789148720195345103412041422309964185732", + RefX: "1565608416074010072069848068516443049723747588995157791473041423224464071113", + RefY: "2218762241532924488201818817616490989654675318729050526965625018299206554074", + }, + { + U: "13068844842276105882441564463385141226661482291282777480569278128076946667663", + RefX: "2439338689014570293167208007315279315504283590239829028504302123556813225929", + RefY: "2753872921218832817653087904431781105434681291985368591548520091232246349109", + }, + { + U: "21803369030047297848730687850670622355761850195882901985029906454216672041199", + RefX: "1047711974625257106808240807024970344593627288911869240010140865279802298869", + RefY: "7322324094701468430461904760459960179675681111235456884268815657668174723115", + }, + { + U: "12138159086645028628734071313537802305585163308353428398824673511568506824765", + RefX: "16483443167668209691946145902370462086241674553805040842464949330912353342464", + RefY: "471876513941703573466978038239305449789173723270999617149296462642024655303", + }, + { + U: "20596938187982507062320068435157374098755319810401780935299086268095742815897", + RefX: "6880373868658930893788974830198341586592248280659932053572848772813849847481", + RefY: "6342731718271888762347988187042825014808334383892684702159404818180312232619", + }, + { + U: "6224915682710897516566168074267263171085656643286078298406483965144502761446", + RefX: "5863907003652309384403260103933273504857439204413655121999691924837885988727", + RefY: "10289849948540405825493124121188404877991797761840131883906115247896408151598", + }, + { + U: "2248925221773522549651411156378263728193862132841450705878028243158419008904", + RefX: "21710385705571665694657086639297126964479327504865057330254178440662856583087", + RefY: "21019754407809881482663860746395570374187730195058924642324906155171660496968", + }, + { + U: "13641116535404471227043919081842462536888045025201173655598013506036798296540", + RefX: "944725403291402851495796332888156975573813476407688718529026954041927798730", + RefY: "17863562018411905769814988881626922618870790470062124460233764869260785693806", + }, + { + U: "6886014182135201853587640359817477862595756657367997768675568558982995327950", + RefX: "9796206275544997380752478360403088034673105293459283692489402940141399050151", + RefY: "1436360601166649934303843629922676301189081040697989343753090689282590627864", + }, + { + U: "16921431892491613818874577533417171812604001909727293115736741928894585380201", + RefX: "13637049163540888934916475535947516035962407902788788948180242761223921104649", + RefY: "20183059585825959152282206351563048249560775307933214036788627356524978005773", + }, + { + U: "19919157609783071622728518228816257524535662122175578712429516921101498927892", + RefX: "14918008304948413502909743965338007427018099542667014877328360612148452035380", + RefY: "16840962929892636722437759818309487147475720363489205353711235556115940914474", + }, + { + U: "7000781919973194601401050723755738465508694266315704859190268594769872177855", + RefX: "21749384165012149604765468366971235517626770719660545655847573063223650269088", + RefY: "2293784052794746417167023187213359053578206325825544787857965438556944625773", + }, + { + U: "20394550025906768704444905434048006892230750380507521773095623980945483952820", + RefX: "12588447210997014031184926966149290249689643487785845222188670851605556918009", + RefY: "1951830799176579714827974570690949357975941488119799017882549086725948158006", + }, + { + U: "11239094676379070011900628121541337509361434958418518313184379626773207025479", + RefX: "17694787098050671324581995611684539880013679115230156421890577419441797685797", + RefY: "987401310641844291075344196527087000816012077204772793676737129495408837273", + }, + { + U: "18450407701339044359664953069457854518152292962099933490019231378595467694743", + RefX: "5503640651919868300445202130995008009874429867184738352323921008662185895566", + RefY: "12700951676241408979890411055454912402041333104887137878111651987092276421303", + }, + { + U: "14653363436557291536282361731638816033146496939654719322226975584767586231632", + RefX: "2039165593126843254243778379107122263489663510764712521154175018741081589967", + RefY: "5489894453937990578928396700214097129701424135821020841245455009957993597874", + }, + { + U: "2635937027403135888089488206716586088262038272012494696353202820580283279868", + RefX: "20212575187113456468221950681841646430033878093060746539580768703826895177800", + RefY: "16574456390824078887658290447555944654164565749087059618995019581277488095608", + }, + { + U: "19114390813048776719862764831283187732846747964966911682971051725732817362053", + RefX: "13447728071256001230397589704245791521167125567276190538141740759123874141036", + RefY: "11810532772569540163201511784428254595457713004765501797353263910415701582847", + }, + { + U: "2484032171400051494984788440612075277595488561565072044706086372364687374697", + RefX: "1098193973148695513054257924239610925091150794257451753207340264404705363975", + RefY: "16094551787261657260918253289457917076126496249787167970596245077830664653601", + }, + { + U: "1012032832276498704538824965403962365600913866167077022502420659458703690764", + RefX: "3374013435073972304534258615863790339799306477095296578359837185378337477094", + RefY: "9128880935165621995605185650581357460254309037118803080586654516633396019596", + }, + { + U: "4315585018609943212128828026684261058211598904085730732709161760459440056664", + RefX: "2424256507261529049411491334404363376382098915778051838684254983028071758456", + RefY: "18600677064324898013842832197048867442981903982068442508819528127437954065646", + }, + { + U: "2928553250830863764434770795239541883022856002891254307168655097778538992911", + RefX: "16519985259727514096843779320184401883886110343702148415441931037973598007836", + RefY: "1795637629807323677731934399171194587737640050013469242189994583914322869329", + }, + { + U: "12824717820098748631206156367996621802602660477716263457336789154330252315163", + RefX: "521213100222287597083213239265986174722034291552466390676154968584837549520", + RefY: "18948911395851633593562013118459802384187536695222694261994630336504450800845", + }, + { + U: "5532520880780469260069407352137718933768739355460174962080543219304698345837", + RefX: "7224201221114841314653853313574435064026638326492653401979619835106449433116", + RefY: "4951466316550350339577608631649387835414958484073036459467553578802458757905", + }, + { + U: "20019180309282837298460739979260031070437718987490085673098101379109680960277", + RefX: "12094504924622435234025948775018831216506483833960731642486835130044963700745", + RefY: "10768363374938921633265444625425607549417497095629240176588336064485781795525", + }, + { + U: "1957980877713427369486339361557110392274161595275111344246601990141166329139", + RefX: "18281763089595201493677572331249381148729225681054026323293511390628594129072", + RefY: "12395590023879823610933154993084434194602438121784332313207146201928646984897", + }, + { + U: "17802528297656850700326389424423030586475136946792118808584423005797858324442", + RefX: "2572416627303080005349934291291321849890171234508794686447267524451633624751", + RefY: "11403758367534232102829859318468459543747573146170103034757570557369280274830", + }, + { + U: "3062039960067811885249714035350103925884175125700035943727523851648923560766", + RefX: "20298876171437453522368833982354057689600153263288768853022034896878573486883", + RefY: "18239129214584784649176885870396581719104370291142129282813077756580249947760", + }, + { + U: "1238662186273723640597079004702123327480917906184683273630957856005710970319", + RefX: "10339232317968311539998173659292723400802065765849762420808724614790044999654", + RefY: "735189435995938917470145686945648160031105882870545758541099586174376301479", + }, + { + U: "9647293211441664372908199772919629089955513524618222432220305803515715060309", + RefX: "6816063206276670608454225436695121743361240953830145838807377391995195874889", + RefY: "11150202003196579351167575060724701506719026342084902489021797821360561336933", + }, + { + U: "10560820600209117119316809637230374223813546329252378646977962710429785065574", + RefX: "8695085262921136861634555085415432011282675740279111382541112371238141923612", + RefY: "13216846438489762769232163862975717755457152534759481989354554155139164887462", + }, + { + U: "11530505860645875318624085988547349752773296868470769211833127671417995989881", + RefX: "17243043183399942290054319024070052784854688113625714562158312630794576743068", + RefY: "19111541992668142152264875150634880735410601274055894542345543366323029990767", + }, + { + U: "1101524742032511653896945701583697383863985227605470931340538975116278794714", + RefX: "7166166251356807171903837095948607289099171240623566128107960187392827004865", + RefY: "20612692852743171765923918038301445148452908985416953571197039944270426596618", + }, + { + U: "10182746373086933697356586705720975980285442896566837017794431726700407155305", + RefX: "9445017289079347827193134633618943756790814040225132922684426215510582158434", + RefY: "7795737935935160896632036471328840720453669835152291289258343739934514130431", + }, + { + U: "20960620787943502305730231182689850531907467694540470252862731971330804788696", + RefX: "8881169683627758605144085302367246877602831031494181318316976859582028502474", + RefY: "2951960490481377182882710813788284254593997191648877069794803184436868570670", + }, + { + U: "1497951445488430528473333115991738476196931209039296318228952235782032382482", + RefX: "5327747616954145224464642035377196626591496491800082206920301605804127066424", + RefY: "13427458149389893042675041963205071049510870361010390548879179703860917471590", + }, + { + U: "659745297275123098032158524953259206187101068371218794174932780307939557899", + RefX: "2501169467893280270583362545937047055917092000318511980427577503562268692427", + RefY: "10473716755007792236573453319723839151662613158659348607124030484791419829269", + }, + { + U: "5881898711642960258698794850717030224698970520139947920252354717139341092056", + RefX: "12155320305448746540506376797512663212927856715457480379830381667144066795801", + RefY: "14315100252250466868111821964076837616573023299778133788391908004022281144992", + }, + { + U: "17080429504984280691280712503048097490530615896064581489006047567557284231762", + RefX: "19564614606502078231271891575773289555361952754044658284279005151157110592349", + RefY: "11507668345617230809996758572928024933171710839139854352320838654689816102682", + }, + { + U: "15695839828248842662021179425600135310171819288856642067297601833009573847167", + RefX: "4113664360649929086294656766968402850243272169859705518818346019145455173684", + RefY: "18993480957917435866486200778455677396977293870107011830085377553997941282071", + }, + { + U: "8982996495736029751133708525831251019828105634507950203094007553590076412550", + RefX: "11978330798213120168317755453250711239071480507583199570527494459038719211029", + RefY: "6874828345403777808843824974574601521802025239123968509475663399923827069240", + }, + { + U: "18271287213566419514020051628075976654182770539590733093185094051546922176798", + RefX: "16326303128929125173414378845547768283615075152214943989174870774306686233581", + RefY: "6407015783109073813156756334516590514073250123804877110270401876635961641952", + }, + { + U: "16885241622369680955564555351089338104569917844747830891230499403001349525902", + RefX: "12616016198625969398325473676273096881983803555760861259164853177147763858965", + RefY: "1127246317013751261962700627413070207493375002480752835498337657105950664916", + }, + { + U: "12266744834276362177580588230840993812335649201402538908352496975852717953364", + RefX: "1346826328294178165056134554329190986103496299362785632261409238776296516723", + RefY: "21814955493083633625795674276460868107132867156956014192101635868188709125400", + }, + { + U: "9715703360652294136855165661547786243219825104595567137730504578929629909913", + RefX: "13905204285514259078600954465793124095796098039579277122158383148389701601646", + RefY: "18750166514371235589196274271930884593285485530331306034107313522840544191941", + }, + { + U: "18388034054169461352801434357931419724842716965310605985282706087860713282961", + RefX: "6244791736412132088367624128205189788611632754471316204539627517643778984841", + RefY: "16638823577096139623987606195672374507089316125497225572448713840915576061911", + }, + { + U: "12511932903908991793041115145218120279434683629049042079652845493373458038505", + RefX: "13625956664904368746562816050809792171382713614394445927189741243547838283337", + RefY: "10889514090156329981649404813170914422267738622835104474213423980778209102829", + }, + { + U: "2971510491840928917772070568307006396546635036397221273600600977784123887247", + RefX: "3323537173641088929786042725532732719229556953830037830245100506172487393850", + RefY: "17856074252500061560935315679498142200426383852747376602660251220972521030981", + }, + { + U: "8032133073221174520607120380069781762049424121715731606188549473727893573094", + RefX: "6226907786310961833910153071585561918798014430111697335608889259738820420426", + RefY: "11434020644672367426885182710180529715272841171509652941479859091428736229822", + }, + { + U: "20513926102972520150875852154908452995583698858345685817252265229545356244152", + RefX: "2824657712746545028504247444114163463196332656989285234392612044429723246852", + RefY: "17701890208444179566382097501880050656781481170669442216677656802469013810284", + }, + { + U: "19655211324760787282301993039265185812315503825365555198724942223881197058808", + RefX: "13574549514159104441651275810725933874166020144363759822120481215441521333290", + RefY: "20494074336876049931513340218755102740624957996629622083260118999580978916644", + }, + { + U: "13676821319259425216605416112325434216082427006586223666053271958678983254371", + RefX: "10021079547147556465425288166732620142485693706426319870947026407718190334161", + RefY: "16282252627608017402594608179185748860867479197815309344194717129887410861667", + }, + { + U: "8435094949591129875038509755398383274058742016047570475449744181000172259329", + RefX: "5649153793269987332216633543684757711508733939640986581329559717036189879676", + RefY: "1282101565400164834258569732238454307380221684882209130868443820864345014365", + }, + { + U: "8696298363826308334036146012127411210104117033875073659678961828078049751040", + RefX: "20938889127177906396761919919073359889958431884158776179010586993710581862913", + RefY: "9768709114185045684834907736714756114002304786392733062566050713735525870016", + }, + { + U: "8615731998610004443503210447115488172277880984542535112672911587419648088949", + RefX: "12269776298324030618839906825057569415820918005273624266137147413534728601929", + RefY: "13553828758413780576255645656027807041197356867592548309611456422031293627221", + }, + { + U: "2016379280202395055720373598044784212999169450675287004670967092696712261190", + RefX: "6000583285390140299394640188546970885722443236086731460636795492570150985200", + RefY: "21007144934181191030355736605021244812489351010432139929713357418224281616672", + }, + { + U: "12730041690255979886210437531602897694546173530884089374707367683004563767381", + RefX: "16674134344751264019530551775726846772491072353445092353488654539881193809002", + RefY: "8895575867378341230972501358761753347830807536883865290109520277246238486793", + }, + { + U: "21358959377144789645642503704582383289885397849940841803600500079056162135588", + RefX: "14564083283162789330607256363540774733132872220638747807935910649777847055740", + RefY: "5367220889515456078339527244627396054522751656841142336556966763220995763348", + }, + { + U: "21236182561400250252805320430687787016273191082335797029779118346196063073102", + RefX: "1056973304988095370328298783209854648264942084907318128961858772829965280375", + RefY: "5445265441556942988516764968952062185598360410940637293197024137052899518628", + }, + { + U: "6818793376498247453906979440518447747430620983702310120702795311977466156446", + RefX: "12488068370942405968554591142729112465783470443709375036131619298857576394995", + RefY: "16323128257318645090664945956647981521752550116834388178202189627733537094674", + }, + { + U: "18520116234233898494567835822143484031605576610738315030546977474665015819188", + RefX: "20440120577288290084853131174895858007693703114760493547752009518068172252414", + RefY: "5101255882164631639380941408014465273580080434831092684515228086422869023282", + }, + { + U: "17705129277298146204746560124389705961606758996939135231701417770862715719605", + RefX: "1162856359037974146811241529855647732266752099603636084628353597643866624001", + RefY: "8528322450282521636890717736740577226208909452213912117682598373481509939737", + }, + { + U: "16146516818535170456196441086907173475287637079102368244275358798516056797410", + RefX: "8569725958311527278291409343849050081979066561886159281943098280263652121248", + RefY: "9710848553691196383985452912130456755534863485008129113240233849498401118654", + }, + { + U: "8745761509133876164088609290416656397089675289971910903278182951045648695522", + RefX: "19283393195059359680770281561552025055712429304060496463986595365494314523847", + RefY: "18449933768133313472695552504836854421982310061390448420852157182680085243990", + }, + { + U: "1904237467173582994316806195810939306113946945966552031780391370564147013840", + RefX: "5553122879520290471313376053355462981531112831496826908077966228648241499309", + RefY: "19021317599323346714264613330866699027963378306724212245279649219652796455828", + }, + { + U: "10743040630407018918296275208366378909593453695849652381171865855589244452826", + RefX: "1303961372655599849067856058986206633623855898270084504071899607376757927886", + RefY: "9961145886339980017332050945721319990756005301009327660255902794922115213412", + }, + { + U: "7182466299723073673867545721536598243442307495094267943329961910902608989300", + RefX: "1161523850750978791226462018950361291217479408673939924268682138019419783616", + RefY: "12874052544286282460370319023457950322952207815551797724245000154747192488604", + }, + { + U: "4990477577196350606415718876026450397776678624011934194132835474975125686782", + RefX: "9695997975938325692871325660456070059901532097013393880594352628057511968665", + RefY: "5065641735949660749737385695311938096509199863653696647429895572085703585210", + }, + { + U: "9292865614568668410629215839864828217882945090163871234099671536301912097944", + RefX: "17430631485213621261112276844413471870817138154722375720209845269596701296040", + RefY: "8465344090016107853497761690968695458388593022773911803932715610115566114778", + }, + { + U: "6504565252138056267153428482732867748876130858021056875210530271186048496016", + RefX: "5000225913521905223015074686357060988370454980559832759709618594788617479316", + RefY: "3589058305938656125401575892882228831980992902662950637124613681757071141098", + }, + { + U: "17665754470630152925482496822556792647546797170268195924850028879867157525793", + RefX: "10511017150443251983258616667358716597880016438075660841177375529787296077921", + RefY: "10003475318917608676174728299931339410096119279807921590087734562973017348097", + }, + { + U: "14792892213859980731276742578532992902475239929546883611053009317839464524924", + RefX: "13314174721537656527790633910217463755355696274643689409511912272312600122827", + RefY: "17659756762182844970516935950030529192878410516811431201722341081414403649904", + }, + { + U: "19084298979654481431443695289284371331965209405017435553808844171394901677167", + RefX: "5336140459322357279864438810984974211466893815463900008880100038029157330637", + RefY: "1218290448831993429640820008703865747650558832335617113244596380322620369839", + }, + { + U: "14987540994675103031908908452996576161197718742436893534253616823947533804959", + RefX: "6289314034015621204070899768584240813745674219005552468073974054789612852532", + RefY: "21883870903821668354903036217923925223943297998980067905761665747018751889263", + }, + { + U: "17762368892899722095880425820446744844609537505349860327005117874127818993013", + RefX: "15953696050607056675689393118858513025329193444236525192360430630646451029780", + RefY: "19375539679606824326270064767214363464428227144688744176327988927055631237341", + }, + { + U: "20504615489267438747543619317722493889183603876445141493453210141133583561494", + RefX: "20263294293603717975699735866390666357987022856851690562793479805270877528999", + RefY: "21317091546448751015237700324254861019100655707009985456089915221681466208048", + }, + { + U: "19044126298744157085879125344268515813472406148763240240850664544312444590382", + RefX: "9631157305416142925898226141473848730931492629574992899357287024290630891705", + RefY: "9827924119429417980541096687434283355944712444127919500485983535221581152484", + }, + { + U: "7038423075254778346127356888140345616808316315372197339662946716660427800171", + RefX: "3567682697711230268160801149615572230485926119422316955136740122575091104394", + RefY: "14595359265147069355493543535862949119609627753001092709137378586980113737553", + }, + { + U: "13840670302129079865887192559239440762856143284246797543615187047075053949618", + RefX: "18741297213500036371720013755072104115149574296462513864878659964406923895061", + RefY: "4384758525197254728893008257688941057522180694371755782290235275968199813830", + }, + { + U: "10032504219686254131933058137281886616577772428598992440541897632124893938274", + RefX: "18827344117905856481775918800826126226288851654626638415904167353827382909033", + RefY: "19693581511907674559834956914651381705029653790352169007568097433494571058050", + }, + { + U: "20191746515926180923058151644111442108435305966033030378319892351137338911939", + RefX: "21535286119586327049741225205391104865567486738537118963769752230976589029775", + RefY: "12356559465493447580010415936009563048216835463152557692229596612736147523259", + }, + { + U: "14439059529108196822136835453875830042822333464651946738329895558567678496746", + RefX: "19971744942383016943975402389383768782317772979190501423819137971665615629549", + RefY: "5940764954672348099902962616656931099623847108876004816654218902863082661204", + }, + { + U: "16229436871162169031324579500726584830942005922229217339670561209431292968866", + RefX: "261281557225227944416854918059134424032675907924072312333161642593509814038", + RefY: "18838848097234435998335340251755531910221348666480178438792895504893514141184", + }, + { + U: "356490829857488993165468058257430719776303690964602987685225680148221869609", + RefX: "9145924725427867557029828438763323689655763939798838209841036098351589191999", + RefY: "11455125088487167506023784057264485082531667677961017836554480388507609815075", + }, + { + U: "2785002715002091274725257438245662393728045153129717827130207260570451110301", + RefX: "10738179633931256174707754779343925157953671113300808690781886247570025053629", + RefY: "10095955092969960903254160351179269419327774952447067581808237262328797230729", + }, + { + U: "17388176514206577803706706114121784066766868797087417959173360365214813336468", + RefX: "8790535768153334090833882269966206312528747788731332512808161539820424479648", + RefY: "541596542581009513486859389450455747039190871805204452906530314798124589248", + }, + { + U: "1665769479667267205201161776600003073685953746481952541102866476135538277859", + RefX: "3665693081849670404776462917540586647104111277267394023073607303815462658045", + RefY: "16349318705367968555440728976775493376513404394136106903878911602802099736715", + }, + { + U: "15425351958970973532689928755075051056480165265156444291216016003386177154783", + RefX: "8884352251839482873684803388143539746764917534749419376279783281586177771222", + RefY: "4234804973150838598524447108581180947608447848965705704503964122979860330641", + }, + { + U: "8179466490864188018408160919036196864086231041549218523603518454928753968594", + RefX: "484161468846575890658841026046745565368993125072764797549268936010958297500", + RefY: "375873779835787267556296939531429837835889761408061707664073923757873986168", + }, + { + U: "17553963477159334624377603681314245889625151656732771906001308832990342558424", + RefX: "21590397528603826255019307803213566605802708573479213676889006181250665817131", + RefY: "3487320494998982108176333717805689888905517673293103329133834424260763502124", + }, + { + U: "10613546133574082036267748666845304897204443954933466160759960786835701901319", + RefX: "20520643414464227314256842024820445205759490778072046145848331329389187894134", + RefY: "19822187894275777376868509922128360429490261621154327280829107217409094914293", + }, + { + U: "1749842585852315930991605021278961588737792655747673637550708591844987648267", + RefX: "5904193463402782542035435644779646799391433894484180921269190884107061237533", + RefY: "17938710954054429879667842637036072722268048583856227378461938431159846003459", + }, + { + U: "15469419173176914790865546152398030494581165334147765584050693903859309804014", + RefX: "5549733850048536613440323103296100022678451133724117373739196702717621462931", + RefY: "15248357841754171922393694919166838354732518375190184199534278964205152020900", + }, + { + U: "17245692137236659789689878611035074810962096799244963332284289099247782700081", + RefX: "16279829255773276931786621259859488566821040139175734080328318435514904442472", + RefY: "14420234238444865754760904540655718954970094664868353590405606877202754768607", + }, + { + U: "15609734104688963035507727303633475104267315165911197148786188160583055610242", + RefX: "5548170165980927112639202447665522850818897855007020865042833270692252954080", + RefY: "2475502787339551982996466830926793595445934907775674441274630722545112064712", + }, + { + U: "6210992160831593630832988799418875460073725129498419447943946052347889969243", + RefX: "19811509455591303038909087939713796730346531663377958055506036277207082306283", + RefY: "6647833204512966941021035571227931814741441737989119409708831170411923898983", + }, + { + U: "14688449000246302511540415231748691809550493297669801548468559521791065140953", + RefX: "13663530262696623953413249708756104072410525550458231677496121396457839302421", + RefY: "652864515305040680016967590152446245379781465401020482080557705073722400795", + }, + { + U: "10403357165164458137038204100576286255853013391865917776423706713735018325933", + RefX: "18108131736472118239350841837803755387183014839583206027853302448068337905388", + RefY: "9125132004051082064957464353426267484539034226498568823898327761213419340367", + }, + { + U: "558323539742789185848551774955878751150411249058484133421441382372328716578", + RefX: "13308189574895439317355674454174339812263540607825532013118992825467076915213", + RefY: "10928546313727912686672026299004031657574402081957912329438230553138662950838", + }, + { + U: "11643042654400942010011248489653210433687748753126719729892219101774694277883", + RefX: "17684297462466534964415287686628841461939617943817784067849736768903567192118", + RefY: "5957035081006888368965507971820105510066294977752448803396720888517648674805", + }, + { + U: "1553234551142763798391096644752248351844568063425266990560364652895288861364", + RefX: "18317383142994334253176974587829571465064011539309316190206135224603742700107", + RefY: "12232891189312331663739537385027811898197147936416346594424827935731506607248", + }, + { + U: "1644148020213546290718177134348667381208162828664526831429101765075728725192", + RefX: "7595068772288715057504389360355694463686590903603164043213432488654558285827", + RefY: "15071618349962679559297803982752762193474606507881089573948548069802894827452", + }, + { + U: "3727173992972266620157509103621474335249383038804773430522061952714853203563", + RefX: "9670670069942186578576788621395639765040368495896413023887184808202927176079", + RefY: "17033614844877697802771894354741405493324193730161310513403141158492323007001", + }, + { + U: "13316521016788261951303020097839302864045780672254222666839896224884316360163", + RefX: "630947893650761274029439097337875340369409146022587313143741042335455468598", + RefY: "16892508633761403046850493166681981617755816855094335595027612087647102107317", + }, + { + U: "12400978990444375897310973001160991369495372310655406444903730097946679373542", + RefX: "20663319321747860745212574765612710221059257453297272232352063711502437384409", + RefY: "21127344620543919055285472281102707133478714543999495057995086751360334907178", + }, + { + U: "10231437534589571931749340107960330180676041332837644017033250993753387366523", + RefX: "5694775112238695261219492356262495449234554155778630902415582462534222413945", + RefY: "15761113230749150497810632374101390112421518814607306578810176782003420407135", + }, + { + U: "223743806411224153469636694872711674492844810083708859378021001619560453543", + RefX: "813020491856159211454506266798101326498314968311384258674478378846560381608", + RefY: "8607087558859141928257940402547899924790578874268455762115530171654104033045", + }, + { + U: "15835372675655749853390409305731530189675662165548563553273100734992319242866", + RefX: "7226648370118231041048023020183462785761116118997659323789840063531938340242", + RefY: "10389467823626962186423694767959288219904192613440308123382760782343258891728", + }, + { + U: "14047653348912618426756815742419821602867431838420192366574939437965828108838", + RefX: "5995976668931087140836138887033677381402827954606880766022411028056011701287", + RefY: "9906195694701250128948090638068084305259565602226454575493069892135558754820", + }, + { + U: "509507792010611918048975144543203395141317251587702373942863587475583853837", + RefX: "19234768982341897052721740445502055112264291445182339342753278658012826259344", + RefY: "12043686023695763408357243461892674714895341379092227068549834056667647548343", + }, + { + U: "934925444024841096525901663842016919910604055517915749223884179029995736843", + RefX: "9301025514465610753350004365646906358169478030205795575251366346841422651364", + RefY: "9962366395525039985001319921456490948863903017407140888590378105008668568559", + }, + { + U: "18242003263567299685892865602776713792666906839267445217505876040859332504011", + RefX: "13090392755971944566099723633949685929639603400244871750934506737576954532526", + RefY: "295574914766886297172653483717602529288225562450003711612480051090589838327", + }, + { + U: "4380013271839001757681250168110540263259320131321180957611972000800074063868", + RefX: "6721203501884057225458061472493806420099141001845981222450744074052680915281", + RefY: "6106578353828473790139685788258601311902658861660908158867308979068763883704", + }, + { + U: "6084247670177808094019651982735496618642412406076499049688907827382985336720", + RefX: "12341572864070860844582508050270733446373867312428648126284468792998228535578", + RefY: "7406185618099754614532071024923780502947581744616244076486069055404898518164", + }, + { + U: "21332755747480273937283013665756596442962886657610995965985135151637637676453", + RefX: "4105070941320073459918509622043317785436131368790740482144215840779366074513", + RefY: "9706084410208534208517332000452448268312395419977386035626667108854894142895", + }, + { + U: "19385487623146829217604598336718948465507187710953627697560492159893497501586", + RefX: "12248435056561693597227284153486570127730051108216185378901296981006235209177", + RefY: "12466963204370930647251696253144919027480135036037923571439492719793970942332", + }, + { + U: "18047223168653886388686753992124037404791584764219281980736209805363222960858", + RefX: "2628719977408653779790141451431501787320069682242297202170161154558756213851", + RefY: "18431187601370618227486028490175111641032573546440944861266471504096132457688", + }, + { + U: "5860254155640831609681051093459101895614295766378247820472956301986695287730", + RefX: "14325601803288503929619169573342286589412137490488349323297529132897962171106", + RefY: "14537039188914041450953137552112806912657884965804728225361320838477550024614", + }, + { + U: "15328841302918625251222521019510550493851650307263515069122698085412154497509", + RefX: "11534713245346644279612230286410985745541335585043428020802433132781569840275", + RefY: "11507218035009098818453702103626899981297698553703776326541909456719072168601", + }, + { + U: "21852392041252261089814719275356838217207313617793442289114219741788568602254", + RefX: "12191838599613121740052842959672818464964474219196887840462042351635478507763", + RefY: "19552006564375796801190828775271700065801772666284712489573347574848821535444", + }, + { + U: "21581166691105189837805238105964832367072906948973957770294920802858578158422", + RefX: "19941096594314535073442393088866403225174221251735433075818020488044214357859", + RefY: "19528586781721620789168004599721239866668609519737271676429291102038075568094", + }, + { + U: "15019826034240582608593908764409404441767270386735359663286774287080592856307", + RefX: "9289705132253752716116745950170692336292807744543241982547367421679980660103", + RefY: "508283103653753900048618825353623187452076101057643573481733029970402517497", + }, + { + U: "18195877945707234114066348291985457354738048821259430775571914116406500719164", + RefX: "14938563108840416383161372194509014068662186602626220214106826306153337191300", + RefY: "7742983469736416207804085626142719326109835603843434498177274806204256589172", + }, + { + U: "12489547327504696889997585817777346536575353156436839795704314663480809295971", + RefX: "1300907924022644657961539075411033382967742826418546906855185467659793490677", + RefY: "4003132606097558142358218814914082253507384011933959797888163540788666802535", + }, + { + U: "13639791439277885654647800080551008071167665192140703030009661812979506760040", + RefX: "11157175563284590679057029535650068564441614082884657942004051859647073011278", + RefY: "2809165382538353295956635565942033656879894078279521984914430869421318240982", + }, + { + U: "10236548746549676567884455775610026369386116117292188431484265809717216045250", + RefX: "12270548507677845477990553278455858854296731747070536058122072120028946649653", + RefY: "7269638571903516923398289729222128408307040729976546905769183846581030626012", + }, + { + U: "12055811748949991090070509169537162729766169481193332586452708675413921870036", + RefX: "20801941778030933725938073840445327955751892445366895644399213305767829315496", + RefY: "15762227560848497300675929671640173953427149342742189999818881156041608140290", + }, + { + U: "13565611847222816844795411334392067986408942928728493322086569413796141371236", + RefX: "17861565893074849546166962713935085930413150230793422945140891677133827546649", + RefY: "17879168240794353528379693541885175764976448749696389954516500635158704961080", + }, + { + U: "8375310136966240332178643987060838108685483138492147598393599415453432063028", + RefX: "14024689799471355675849457049942533377770196300427621866004617321753470817105", + RefY: "11119405588081745019271441305598241939362978129035758459564998831947626407212", + }, + { + U: "19319011443761965922351908762475981695650661608316701454832731805499274519915", + RefX: "8179668951716490677778384806875391313038447617869553227162119228870877463595", + RefY: "11747099072824600998516994619214496838462993033790173087892159821477958444575", + }, + { + U: "19729130303299195107779440126864533638371791519658902827496440362220161861222", + RefX: "7838882203763875869710851066366493224380895544637403966965749303160871665543", + RefY: "15154067334770682408985584955516310670205148135406218760497062751434437297498", + }, + { + U: "6242743750320665807526141027807074304827208667173369920827296560677968853074", + RefX: "19053452115150430126119291661494642007660993951909184304763009500651360065770", + RefY: "14759629251245906723265175515701906383102090119270535263850681369215844520860", + }, + { + U: "14596884571993979918340086531288101030962956930819741692357988010717026727347", + RefX: "3837096864354028762069182467857332182571623057318456855505529321617059198182", + RefY: "1798271905414754463922137205862081393785316417903887946635501251004618825647", + }, + { + U: "15878055305619329052945725798659379393628580876110306572496536503497879300444", + RefX: "6006912762756839314863262748968907909869015305970694593608858718420687030299", + RefY: "8753227557155485401098236905568585885238374245469920939640244351823699743840", + }, + { + U: "13897949386093655145196982875523817930463273788312264818465413044366170392149", + RefX: "9416532751017756852780302225896577376723511805655299790890488795695245477168", + RefY: "10572281292800367818667520358182178169647939470772310520982562959634830347569", + }, + { + U: "19408182350510162311784681500274860613398343073973508513920567898568604634007", + RefX: "17870888019204140552680766007689790397978641990732934770617813687152814673924", + RefY: "20421410475010466819223124595690102591040006800528582130755307867573758866417", + }, + { + U: "19343945069413752311217214056208490882381295735890324099381706711056300198979", + RefX: "8893525503189470129681304636330800057224726850229383174888303991752202969625", + RefY: "5807380035431598164738189447890130741659463708561784609035113477016501565969", + }, + { + U: "2925588913416884048905519836928276142329632910376526301561653780965632572568", + RefX: "14874251355302224460865590877624206906262134351471407239009556537037778755121", + RefY: "4946847860009356093751014040306705316413791125534487207726723235486401666058", + }, + { + U: "14079390619838425433113655900416651763578086194807741445181766715766689424975", + RefX: "21847141079987643102865413551936147794285588207812568189329961755607795848982", + RefY: "11090428206932111534715270520823266521214729156636598404133545843825431946747", + }, + { + U: "8483347042582897519305156541165990486112046409207365087927980790688015715540", + RefX: "11779228779490894144630192552426137413893731085159680221223630218481348039681", + RefY: "12291366830453156475936843228587053093232968540700077121221472945677648036440", + }, + { + U: "7592670489793991395889796872419458984575621540043763287999714173809492779747", + RefX: "14598925038221319991043405049522040039309663541491467620612036843506575614085", + RefY: "10135067619792475320771074215894356539448647208895303888773562012847258673727", + }, + { + U: "13158915481277783934079901140892892513909866347505159898666618657763735559521", + RefX: "12069087115283368644087757532624432230841397872305034979447122765633919069871", + RefY: "17171588557439586656117600557615703194293129494038211500193861880793804903251", + }, + { + U: "1907918313689639938870814652771162929477984321347378419410573163883915901916", + RefX: "4331120379212682912172794939204600235890833635379090432344921987513464793263", + RefY: "21050654909472038411612369641776461227330401104972063140577884471951578637636", + }, + { + U: "5850018397086779899553504171496733355288759902500674142445340887147389386428", + RefX: "20369851587552430992304175283782692131497569944584241475856233002839719176303", + RefY: "13995622948521780680822016347402268927822345235119155953497732277383633966954", + }, + { + U: "16825823960794000327447968851874714158455824893846885586719365446355445274177", + RefX: "21064936276095023384328106068963462837577283426057021550073713654476505807655", + RefY: "19677389792001090381279195348725980490582259936920440920540838257998924799975", + }, + { + U: "12290603619391849787637718546137606575926545006861699467857273404677202764989", + RefX: "17279345714655047677144808269880213817415018689640612189944963956787350440201", + RefY: "9764358530923900987337250192306208155219578472011252243368108301184404113323", + }, + { + U: "19422913035279042107998035516301562067357613640125900008172942502518542996059", + RefX: "21518899857739390043322858988939520048698657818897154387776310732241923119559", + RefY: "12349294798123545708875629281767014756223507769305877931641043039767468248371", + }, + { + U: "10727636024216131007129804292694303960825775718577074344682210271405477440969", + RefX: "7689148912142453498583349454430695580518122325655446330676424082200613970466", + RefY: "18611056948744730268195370133811409605866310031063600596261524606638350156167", + }, + { + U: "18213935228211078871071836821619511267662021775344883493350940767064316792565", + RefX: "13542489427818493929528614590250800407198531949099883940256403052116314496819", + RefY: "17746090528954341460407413938419639640528083458690930628733298255243651079641", + }, + { + U: "10498863854694233241561037276503706000677961290832877176292838053475883385746", + RefX: "8205001801033845726056095102470241398453602353626209663608175485654692580182", + RefY: "14062569335312175672328362822908166777463248798296052326730302328661739736940", + }, + { + U: "15335905556659551160702009199415966368825774401441946113102762341922740132171", + RefX: "20911126754202731660970036456070125178657067841523756692110328040680122500650", + RefY: "12116886086148762637309392892707790340306545725808307220187534872215581433469", + }, + { + U: "1656091000226675222957172992928463583552184395466097755605986650200590944367", + RefX: "13472122369450009505619404665263102211966889680396990783772275399663062528516", + RefY: "11917161246190429636330343567713898962960542317508274882415595611032944431227", + }, + { + U: "21091379028693000585979664755189829887783594684833003152000451221634058849031", + RefX: "19782594203130366125169212897037516231020525014743143718257771348128630198795", + RefY: "2015746900083689050887529096657506825079486122326573896040624224158141127591", + }, + { + U: "14413449432164257632443521179730570537307389588614957454129296369187697627136", + RefX: "12673978563954551388755208271881682264946306074499274339268308139625043615677", + RefY: "5657749029952112548146164996554087384907358450311097933859094448733629018508", + }, + { + U: "641157698235803296838938500278910920475378310316059348257813548739972832728", + RefX: "18320950609216896060498084418569064210861839062504657683095467411175682066262", + RefY: "6986990647238559629071355935777922527385197819611285048728483823194191088698", + }, + { + U: "14532139752063088251947589653626419005099009074756516206620603383162383253197", + RefX: "6033408115824544647206141774380688690715987790852941123854392655109329999450", + RefY: "8827157373712922899000194684805959689753358717548612001847472607474018586035", + }, + { + U: "6041670742202286757730982955651099937897993314400914937581687078364949003123", + RefX: "12696899827924869268297770329665507929635161590913602404500894894907178683621", + RefY: "10714112698142924647919331857356210196249968287955742400333282010079473400585", + }, + { + U: "1036690043009893836836596508959694158566933312186596634604909305533932833888", + RefX: "4814948264312866121164490906308443122085476637873692267906730466410448024267", + RefY: "6485086855889177236761734306262698470909247584546145905879182423244174057044", + }, + { + U: "11247861486529097830242335973289196170392555615045942562046885013235437613931", + RefX: "13177156606830895206152366813268402337812879652732676852609285344104346043001", + RefY: "19530105421976127705293532097544583715242357952114981795584069185695462423217", + }, + { + U: "750891082902162529858131450480746469456292478233934377330686132327688064368", + RefX: "19714388165156431977589096928884617235925570684455952275079765056659442895209", + RefY: "1674704720685648533779674441264051066099132787854251604088185991805282968852", + }, + { + U: "6229975149920262674545141711768575909026745904138388476684140958189885058364", + RefX: "17490772022851648808845211399570857577202035500658940686534431956359964444259", + RefY: "10237204410608137088878824180941544772802579770442223461715305354255797388550", + }, + { + U: "1389465569034755326576434470319044972892367696955685648071844707918705789192", + RefX: "1864357114464543561416245753971901291633304954790110443781963187507970013774", + RefY: "19785037499982446411858243092960884144447545743624455823817743550696168625704", + }, + { + U: "1481372153994408191681025119278900691835752655000764425987450291390959174974", + RefX: "6390417320058695280279781311745956216740715084127920935648696127821079652397", + RefY: "16707472207172280003235175931373422488461069540471929923942110535541851551324", + }, + { + U: "5994623412414552686874693246389228784278038640883772531145231565847042869063", + RefX: "5917382025083818449087412132685441296643444509529049877561682298207089607973", + RefY: "2102659025686942644482333209770367171384617449850191338281207382261809065525", + }, + { + U: "9534834143842431541286235827898874726270809691183467762051452229610377368088", + RefX: "20439257986097689328305595411296342135566505975108864208291104523876727073053", + RefY: "20572456391329932603924523467180211959602875303141036252684444668851033958330", + }, + { + U: "8259345354525408277997516513457273479396966545976157031989446195443139074242", + RefX: "19676868068856629856715194636925322498906751925028534361106386618002228743741", + RefY: "17304525967201441027554546214772673920061380118951003309947627530479266936880", + }, + { + U: "19266018916224358448627928075149133714478324419789510273433651471620060112253", + RefX: "6872349322695732118001314071006387662093105613346393580824910182022098126722", + RefY: "6077709288537259047831035776012256712143318171291766663257870828083508427599", + }, + { + U: "8624604429103825602017624612360479019392909459063724842724749188156248287424", + RefX: "707597193177927322418351410464678012294855584007683924898662032608168638139", + RefY: "9959692261776113839175854644681875601625840435187186948880814325880058711514", + }, + { + U: "15383136596972878482355380288412727238830990211510482006976352360414895209820", + RefX: "6425396387760357187866380164970133199143816828204559089496044704344420737852", + RefY: "9188565069094645797540650688639807472311896559611148468281850680794205314426", + }, + { + U: "18195026711781770667308382059090121778714305494245888905867867810600991766195", + RefX: "3835410567640083558761286035319503717174906555606607152372895808730057563666", + RefY: "6918508483422296165381360667506187084068992982813441569634924796499884044851", + }, + { + U: "17941043998502287626666031793477489613930844355097783300321166731120451659533", + RefX: "18820073644784036086290707135526506982677949977004189252303041056680039391606", + RefY: "1926575810583151459585193565841807107687064911814901028018973481265479931965", + }, + { + U: "11796238648675758072883223484849394748383436130223886082084132654367157871138", + RefX: "3854864209986737386996728934112115739695552147833828988178460851316750616617", + RefY: "4846466029024421984902890244202760625147085655969567550864793598709003626662", + }, + { + U: "20716562102711214269939042506895113404251957529607481355570093256807551259141", + RefX: "2985640936530841588322688576454368891820178079624824744353509896145718078515", + RefY: "1599490612877755967952717837431883482045033846638428113182514293149018207925", + }, + { + U: "13542902217503826713911788747625731317797369020734317464373226524069842815394", + RefX: "7177404578996263353594274013421070859333358516420534074005855145424543384315", + RefY: "12774118085242568378041543798585930890676846401034590605835457036329668659972", + }, + { + U: "7597351885872943362212556508773058400536447907390307159142305633050433031822", + RefX: "15788414688214299737304031849596232310279890982178561046130015774435727162495", + RefY: "20257514997641417599916784522134585143983616544856872842512859461967059312488", + }, + { + U: "11038977556389929612471028070221856228156525687709603887238994310696775612064", + RefX: "18078131232864077929140586073884103787838833984643613763175202872154926630929", + RefY: "20905764999509745751912259220985994862140469782807017847791652034495821317640", + }, + { + U: "2216500437352777168340125463159211203620938625178187733354730214536550816788", + RefX: "14605516759669112645756563992050953844257872884738555389149330159400304844502", + RefY: "6753404672641920161160255691407233427017053767187866489262267029447145127866", + }, + { + U: "8300085053451743097067735409346162720440110189696429647310964407615679221225", + RefX: "7948389599738781283292389201033594563672939271289618347266179906570212387936", + RefY: "7596861255843327889411714684840008696165827012026499632351106244047874190281", + }, + { + U: "5351981140359753550750123778411685565530798720563268991712234504145631809086", + RefX: "60229210150717149166661501207311071152567217095563318935747084667650463864", + RefY: "13210630470402375260576212166890149010735948182120045173620632118003913262432", + }, + { + U: "2995740372463339857036356719835606475296675561384249162008812697883593988408", + RefX: "11380411316872545784808256169936727242953066110132886500708080184329062312485", + RefY: "14220556145252752865353923839817446071490994679067523020199891522539452599206", + }, + { + U: "18915648827296830230180406478364845453966653581362477255969724423525162169125", + RefX: "3927183113082505801231072532009674991076875606475485755910706730916857313224", + RefY: "10787873839901465889419463935448016016667195664503507311151134706877296354285", + }, + { + U: "8635380100277082642839008225059653113436945814624250415633576161909540145158", + RefX: "2936071828194406340376270663962664824390539382426465445853976078356690667963", + RefY: "12045089168986151078179054539629153277339209306207752936195561092191407583098", + }, + { + U: "14620982283204441589878475961516081665866630402523378187963192774083419137493", + RefX: "13354648399228067283767018487645189068189600948984663185373948314510435675332", + RefY: "1788216165355537417114440127086945676761160430327861634983826217477312644565", + }, + { + U: "6687936779401377248780615989304989755525840306355151873063824170737277232888", + RefX: "17312707618594904666637811715323567342357360828811144546594596145717084138", + RefY: "4323031064891681085762891188325948382902482270583776036238196617081947780142", + }, + { + U: "18824596256279216485480242128359258509038581747941790679160853314456695320231", + RefX: "12291389280529226506246498249313525640153374412302251608379361660739853418646", + RefY: "8102630040130305226899237171684778233857142237194888133686567946934247305853", + }, + { + U: "19012315507707166173709442894930514782461650427574357319671693935444838600598", + RefX: "15835535164705597401008387810832377478871602584740857809223198915663936321847", + RefY: "14226983582319407622780141069546952648182079236124986086744404829832106329998", + }, + { + U: "3097954984339168624878707849636785686831249092104802830928650706892227782924", + RefX: "16159570056917024565642689933014622585699440600141094317725878393629218248387", + RefY: "72574231365337047173493014520486721477671836511915644703732949439523443026", + }, + { + U: "19170690456950372335735922114610205544666473932293326568157434445450509504894", + RefX: "11646857055807097093254040318907725444176414289866044402024000187791019444682", + RefY: "4387646915544291552521429445570143430446481365425408020570327891937711689814", + }, + { + U: "15155368742050971866733617293623068182983563155037589293979174025150859385980", + RefX: "20686235530287405043657818963790512914337597959090085985770482277301536346581", + RefY: "13570446976527933320882142776477350511584182859594999466988943115840321678498", + }, + { + U: "19308966728733946569562948166235939364815974704813532030768364291597624096399", + RefX: "12044428403735915155571513937452102956560069446758096665347511324476801519335", + RefY: "4908414034278219681390062071766592743943165585553760280588701542908834770163", + }, + { + U: "19544353311233224768885750942363322045129789429037701064642205441226941266540", + RefX: "18161101512635707178318115872743608062216928910594949797789775619144281552195", + RefY: "19863533793140270791244725301593507745216034042607506857584837701571361018482", + }, + { + U: "5733120421242771495438353248052987229595383651816851456509657141124424762224", + RefX: "3336074706114902945832610340887744740431387412520125162414332767860589671692", + RefY: "9380567121319211490244787152070348892555071419336558897422663913640882784464", + }, + { + U: "4007503937874597980143482242749418182563320588015195123304583720163736585146", + RefX: "8139167523370870105149737354516206167916817816285337972583386061681771814800", + RefY: "6333777389786831458578531540523795988420983765183228093166264613891528163246", + }, + { + U: "19162631809520237815313180361920039070336450671792240782271237831042804055891", + RefX: "5072732077916598885589233513542774601931084635212016913551490857964552217877", + RefY: "10926334235779502703042052246202708486832179823056038385471616053183792076261", + }, + { + U: "11526016775888110449846965200101338964566988063106411669853514827440893114722", + RefX: "7958497040507732627274331369887680320548559109555370382535969387469156850593", + RefY: "5656358428109930887326041983312560027651547332272367440783389336512069161884", + }, + { + U: "9716085787901399856607066434330456370770611615212076398442381682963981860952", + RefX: "8016000303423637088338416113569219049453663918026275586198398766782849752746", + RefY: "21566485808967919261750629361059482217667428672286872895852466361046589859660", + }, + { + U: "3387106262478333330309351358885740746295353108829335799045750257584890126370", + RefX: "8669625547355716367697331774538091373864539500013420662518809377910217407139", + RefY: "2062111052095416630664234826743424607141751627222284238938456845972280880936", + }, + { + U: "7760726232136382696165692082109019379608161182322816113379236494069766104636", + RefX: "4813542984501478324038098018390514784548972603417168723514797800519252305173", + RefY: "215383463877686804884550770239190598184721773237590141580143696310247367180", + }, + { + U: "13543638359808657053646919260327601408827840711639301887679440722760808701440", + RefX: "13829392657662455476866325463251283417480681068228873732978458423219169786793", + RefY: "8602458834139649641177961046922322552528811795251840749095403574696384354508", + }, + { + U: "14868509726114250437220879189250167583370757505908556162926424316898615181391", + RefX: "20909102051137318489165873890398086755726187793348089091312461656784953890070", + RefY: "21326112986633883144229683770888445229793048928952457687075353770253912102549", + }, + { + U: "850917031709631399654606749532140252399617295489769959293111287546663099116", + RefX: "13744924123435661209822445265450522492968148144458934341012156337369619843995", + RefY: "8352355821595200599437038071262410963462967505392166620241375502498741195240", + }, + { + U: "10258116687603707539299464987216155439077081653565041621386605619110293859617", + RefX: "17284372843271510770575511081161213955305910101053871919487071241244521585998", + RefY: "10549436524782589242389013035018705547258425819615635618034633505806550198817", + }, + { + U: "7084891912046360453119460343834207659744857661845875048186811079268790669544", + RefX: "17859580522974502151710109668170865903467718755257369613204548010307699467620", + RefY: "11616131920489420916624064570925874438170638278542899259252796063156599802630", + }, + { + U: "16501875148129179107053397511369944372757770998601291042582300921081655945982", + RefX: "1302581490989905224623276994411306083345146323719790194503444806197461016086", + RefY: "2728528489873848034605973376037298234609477934276004213146359950116298161878", + }, + { + U: "14436609289556348069888391435015979445962710768390755730790812872104185956076", + RefX: "73620945995077126940123010842921196722056867913373266875899838213490081650", + RefY: "117464177066045098464212265283336619917284638746882362463791072148318579140", + }, + { + U: "6656279127158989733864159590800883164745269906497812314157399735283907093369", + RefX: "14297335295986773709806861432617398356015725348626345259878535235656790416913", + RefY: "5711681467144152453093292744556950950686560010966275849703095258705138161905", + }, + { + U: "11578244585171437740261227278334239956118516460129933483641509615055752798137", + RefX: "6649520370345509603341871961973741344604047355235729014348249848844816102082", + RefY: "15828739203415320470782156149858628669143855767703138588758724772116065925817", + }, + { + U: "17826008493503091191594567003153584857987739527523289310341030449519638071379", + RefX: "1214561608177081757856527603797064483728944401057475522527622158262242179538", + RefY: "2731573161236214573614039519556255503736354350725705818101815926968088016877", + }, + { + U: "14012089225384265988112793627447579554339584292606765915432507784155083352081", + RefX: "1651040292751162539160778637726303935077194732216782893184159057848915757161", + RefY: "7437284679797692035439542869610088047619435007460905239936878875121493826551", + }, + { + U: "8047697987447929833059727260393100568034543033672546820611564828171463801283", + RefX: "3293651137890196315742386363071039750423462047173754688525853031342061787880", + RefY: "19709851166207235829833013441045463607300709062864868164843360539675400699125", + }, + { + U: "13755734040985849371543013037678777996317326559023369830547608596494100088479", + RefX: "16509760380092410931095136073342942101874277065302164965231027015080747325805", + RefY: "2725023337777696745649305960292314494561116809508909679664286392493558305515", + }, + { + U: "14470461435734352015397452728047715239314508324074658731058287745922873237090", + RefX: "2476961361217695785811737006239293988504666973856597130923641064397281424372", + RefY: "11183464216214506231798323689972392250935139647857506104933863557921928102948", + }, + { + U: "3338855332057368873528219642393273065151411531814469941821688588956457584855", + RefX: "11150134881075913852705791321930902869907509310850314143427702985961083250217", + RefY: "17788609828890100433790824852767076337810017423375785178719519432561973248333", + }, + { + U: "19590043582190853260774232402259276811621513633198976427784197507476423448117", + RefX: "11642465332127458665640166931230335588667256293867499273723712740227126109523", + RefY: "17516374132749608935662405839245062698781276718080196986876748171805819639241", + }, + { + U: "14780580394420436092298853974910870317892143649973156019079781201763988664480", + RefX: "19494573451958648455391410060329180778288181356628791438007380819151225959834", + RefY: "17879317131161540990673784510258422144106817641091218163763537731353484421920", + }, + { + U: "7547945570738402404035066143969466382747372658545366108329565819824040419902", + RefX: "5453332704203167036757266996029914922226361890882704847886522147900281901455", + RefY: "2546049864053220854397637965029342528522328638741511194358267297367398876824", + }, + { + U: "3168699766939280015301711225485145634274801005816404259931727420703287804044", + RefX: "11819514010806529438690107605668208896688314388072012772123558694675790311407", + RefY: "6717216731773019161113659658071152194161960144524055337571232564542764230698", + }, + { + U: "19335795337329705682806101439925562170596678033897718923025053856128878669972", + RefX: "9714024443426712629965230592121363617158660153707102429440411439838540571363", + RefY: "9914455534041734943592303640357248341377199358436048502889983885126127284800", + }, + { + U: "12084018321582443706912596710530226401603931870870784156136926728360327988081", + RefX: "3180491351894326663348549531635624815576313456359429304014857753259773832830", + RefY: "14040871466411878886510172563767586611129811154735514338090670753458613634927", + }, + { + U: "14912004952871560995020292397740161987182971037684342171269628705881881732184", + RefX: "11841089584307982102088165916335539392169558806973285525466756145272557278206", + RefY: "1436937666575176159395815596293252221502914608844308153659548425767836337132", + }, + { + U: "20886960330673639479130351229979217199923482659207630877799301647239714470373", + RefX: "20182939046079959184766662860769018386346027380285613911127371041112160055202", + RefY: "12736401093529680121251503918467868663990224402800764799934854689313774953291", + }, + { + U: "14291085811532341282641119857250017080857521709410879862383970320654489159202", + RefX: "4341716706652979191050739644077511153993236223329419289641848364406443247302", + RefY: "5450773420645623354139594273336558835992408650522860318774405059729419024930", + }, + { + U: "11206749910749961723937446215623284509279856080877084419084735664804160516191", + RefX: "870525385384223236225365380944843965402672026039006007833592317831533102675", + RefY: "4160473863680988392024237132737868054959565451584462891299306321625493129683", + }, + { + U: "20811544407029327236530429118748130060300878015128056955898939626593079676444", + RefX: "5372971194017469518615160553213445732568320620705963826783475910485388864432", + RefY: "16516279224310581888723202642879815639720348628568981661302637520206053762726", + }, + { + U: "16415912671890926121373920439786454784316346840153137537888358464127174318782", + RefX: "18914430202391865302617664865220358061028571159749107534875676953465268194004", + RefY: "14843726009714617412917011454994545078475693427446568402399503688261409813248", + }, + { + U: "19539793880392088365508654034067204052662920262873673374390177877818173064269", + RefX: "16023735741231031398515917172977165553607903815130906453484277807334615298443", + RefY: "19269329379765870325909564275406300452781748428620385965673882206161877398823", + }, + { + U: "17240774102141118662188204544786697041556051238919398476465892621654817141260", + RefX: "2446370749878204646610365751349453576411996326613045253805482091214373219572", + RefY: "19850840765533774272228115179722839903983609197987826075391669799692881919584", + }, + { + U: "16814029908591880908896252276167448810856599465990462384379073536755118705587", + RefX: "14196922625636572496273818296343787501644558723180768486509982393906806404677", + RefY: "18486530608028057521369940439183956029638818390346651513590462642141456476179", + }, + { + U: "8198721118380833780010698147626540378552493261180180796092030159074586894947", + RefX: "4420525627845738544189303756941944012934790904728888233020262772387908612655", + RefY: "7643743425268988161378325985304808304924089933455936908890382662061805265135", + }, + { + U: "12451281585994499979978143910119520119633217111163479374188403174270064441006", + RefX: "14984249409768275509343758198007046080279258870399533217013291681875958461076", + RefY: "4266282790880157979325179279867948026189834546397586450841959172813297732934", + }, + { + U: "14735613842763986819373143072833187298506397139703708151715400978523864385134", + RefX: "1773238106940225529262726540945733847317809766072602193675861849548578295166", + RefY: "17052485739036457054702280089385126885726797451430862892548722907543371482174", + }, + { + U: "15486249028137196390609611357925714022975977027295193391666740317165871736402", + RefX: "13048559987518124602481341882529231336768875059258775562504011947911191487573", + RefY: "4706738875603154831700279211527807224766769813485124492964285117694539767332", + }, + { + U: "14180125837911202227525463600320536375202680058626127584260551490698846026162", + RefX: "8343350498901686561499076825828056525710154692285927488522389293144892425279", + RefY: "9797629399086654484960921794260117706155994017299935292749601266200520803678", + }, + { + U: "13047736787786759579282847357929402982996186734006771304352667316333403824528", + RefX: "16642981760637037710324297460250017074489826724845860483429557852795252021719", + RefY: "6485303721050185718398583123971390743632237944872463807623488375067503078130", + }, + { + U: "9263261956640886922261994682580787537672747322693127864650956331199951088571", + RefX: "16253002854967788905060542681331129897544024293363989348681850616459332365390", + RefY: "6485553078836903806815681646006447976389046322487411258856783324218081278623", + }, + { + U: "16412151442580698940125400931908996849449009778866812895611804346326258808112", + RefX: "225636263031624177897305273250981350296248803445492383280084114742229795699", + RefY: "20683955264932945386739855804463496229419113375249897041686341102035724171588", + }, + { + U: "10478667671247497821776330781422692912194443793632030709721482835314045791260", + RefX: "21283758140355872619290091929080250325491651707643289039944562949314927992217", + RefY: "6260032833915617809887758626161573536455537066214675156881031102665157911230", + }, + { + U: "8356094991531307277634873307551230116854150106192267911273335979503900988571", + RefX: "1361874691213431809864973827825358481225721421216099783534178309385910259097", + RefY: "16536550986143758661492123186324404633852753113072462311378133644066639514519", + }, + { + U: "11442821176187412739912644413443017557913091786824775937423429524741696433200", + RefX: "16984420582632563288989537930765758029906435188884577624772203257568107603465", + RefY: "12859720559826611121760960444445933983076063558689410999182995941002100331992", + }, + { + U: "6875348991500030337899396273868351983605561663588533786303363997190585132689", + RefX: "17269024501809105005104671367745292048214705961884778615912294367837555906775", + RefY: "8428896969883056062441164646681235520312636425697419374890901645329490926971", + }, + { + U: "16104781876626885634283682177286063859435894811056886634014358381784715771126", + RefX: "13750750044470480576558707543704558841706818379321405338732300513615623367637", + RefY: "15453348708315910965502731380021769690903021332989365348042481785695414301826", + }, + { + U: "5415331331489078563127185380192910344544270198614412020651278116882597627919", + RefX: "19542627052031356766597595117691603140097568181525291569839384321525592750108", + RefY: "18169014585419699852623911481383580859412980603359267905134781756520536115751", + }, + { + U: "13073714169537780781657402729603356870517873084797285941514852676302574321154", + RefX: "21482512681717611974207235602884436369112103195491477643143684438557815205429", + RefY: "2255552098939282531348689301196599020620397898164859715392857288215824581946", + }, + { + U: "17616800227134047513731679602155605780252062039361413320506753132930060530371", + RefX: "14846895312801799624723287270960403879467357615907396380179048206686216456657", + RefY: "4194594992559245045797469548482219757467026798370784468492845218638219356005", + }, + { + U: "8023144072903159681129470647350243237094973768740922282898303969441494929758", + RefX: "8664620851366602129746420024457298036243377216401314377738595158969919516152", + RefY: "11693390997093042881758725819061172579972726377990706239689485330698540972854", + }, + { + U: "16259516357574633728416311335476468230629807732131385880773010011976486984178", + RefX: "12562917236392133567054365343986086355497424607058733178006725648703195974674", + RefY: "17822105065653350549026259668488184857413136081629487087807397121819242261840", + }, + { + U: "11009346571803216021647705763544437854281265838367566349077653054441482605120", + RefX: "6532332865292791543808160215711243930871803272280528503003196522960711559046", + RefY: "20773154218966462563815005446103864792202554260724046870049399665032505942130", + }, + { + U: "977007405646044062926972236059396329256368766342618076244629744927573210498", + RefX: "10635049607541320575890771111178119024743010248522167389708749933549309761362", + RefY: "15106614881065448381690228952469441855568873307185949313371799772024456013232", + }, + { + U: "17124300677472442225136261945942517633486639880503436247842101889759687649072", + RefX: "8838213133662203409973641462484286497266095684583903008185031490177146968088", + RefY: "19393269104493897508408158626195084306332097513753129125876918014949841248434", + }, + { + U: "20157123179794970977528542737648172183138234035744081015951568514110370364795", + RefX: "401491433184870051609005119532897824006468474459307195866198787410698733055", + RefY: "19369906943016275195332275903196427040393835230626537188767930197771928387153", + }, + { + U: "10938942697542073745330292311375198832332478166532662053596849949269312273431", + RefX: "6125977281219581049494936058082211618945130101532366654818165114900612853636", + RefY: "21739983236744127118566787676946394073655333252388432969024245890784726406049", + }, + { + U: "3987114047500343450048228283405189658149917626081008761748551455475879137127", + RefX: "5105875163993087793863084077738320919907300040512026898991751616086895082828", + RefY: "14617161442223414514442131263565152883456818250045163196600274189321734584101", + }, + { + U: "2219649595312925519552136923196765862581420475822750349896393854299104664888", + RefX: "7199053884335307369599290136294937911349900166325653116638607516392783925474", + RefY: "7098376292736230318681582594442363830690246020455321723700082491042042843520", + }, + { + U: "16354937979314699895368444246581068510358120047535745817885820684078680815614", + RefX: "10917963874685000909264682595873313924641515699287744225938510765977341346871", + RefY: "9487810266954275266128571643678078383842026335724246689265948650024464202574", + }, + { + U: "19435381159578590867907769642828999801237585289627528312178196301568922031293", + RefX: "5240480816219166015745165853385341759289120376837274705273553855374684606165", + RefY: "4795714942255518907625897061932609101235675650847241378009852180304005612855", + }, + { + U: "16106040602415625735698434085144473665296052919394519943506414690876861698429", + RefX: "2727460902276845084374577177639459448976885648239513874280330102244044420076", + RefY: "14984798636078059744801254011444831078555579128707458685122145846470555806747", + }, + { + U: "4270969164644572198260787370337892726921064339514740431183383766860047773269", + RefX: "19702380294767512904396238194396951343751802999798513553069486258139622054800", + RefY: "11078291988674386875668734810880917049077874052585658923997853865878047457107", + }, + { + U: "16940927302942430043074179096992643244326360585351294649938780926588246132970", + RefX: "482480198277961802534958512751811874196802418157828492776441504660773603100", + RefY: "21245037732302939397114871617852949930359926545379283765302919349013495168254", + }, + { + U: "1857315550677081209325319749010737772123987443180094334184488058619359187565", + RefX: "19008552784756851548795083841105673301953327443491195075955839371879312608511", + RefY: "7009663645397314324718283737380876170332204404306733406947957816290120020467", + }, + { + U: "20918920537627143975642933664726931773777398597165194347284954848755162356789", + RefX: "12694167024364672041767858102078679497558566333327644499143815192306638463928", + RefY: "6823505028802771112920524599680897105173897349074395809199301570669162487047", + }, + { + U: "3752604381643446608901856618106109736380128968833068252797623763138878861624", + RefX: "76732344429695412475284525849827619878782991871817684664421592825897095371", + RefY: "3063116590254022239231686147834893812303055662169165217399860504499952287188", + }, + { + U: "17326106768090740406088674927529960884390245592134521162247528105017752909880", + RefX: "11683458907385506826654111479014597868702340149601600378261917992739374255178", + RefY: "2571600410944913058950636146706431408155009447690349461368361975282114605012", + }, + { + U: "4839398301781211333437273174073767564331940372091714145923239280110512116763", + RefX: "7097310105102953030918259763954629688771675362726276932625566113398343139665", + RefY: "7579609819227632913133085509078074982401310815801355365477413992106419067533", + }, + { + U: "21775680330010197978968488686509015368469276843922447332411996004373244578026", + RefX: "9293132282519756987438952336442891098467020813176828096523962818142087089038", + RefY: "5777568450367532203280900007086784840116906162992764235508454068041142917200", + }, + { + U: "311398835017644583704193982281518441960281323289389616615537471638960718469", + RefX: "8615270955642399158500861251118071124652225297305861956023294611684252851977", + RefY: "6107965267245950848003218556183729022923569683538702848144163322237959517525", + }, + { + U: "15358153784517245213073403309972154329022124203523609785260570422323678531556", + RefX: "131404814364109381094547166492022575088495847212389307112827938664111994178", + RefY: "3053315560348655085718005665741967508766242204976955899305933319458704586130", + }, + { + U: "21589711510091003210734168683464452811058238581832285660065848526370073549122", + RefX: "16228742299513636718571032164477255421842834938001678952639411017198904135107", + RefY: "4139005315673427899976585353076371491304006460196998761029553939395306589598", + }, + { + U: "12851074358156948139789037167588356267212084842889900148475118083938597195181", + RefX: "12809757922318712690044833503754610419032936041576395606783537625725849638647", + RefY: "1057962943555379839247556575747141590038746197199702688493703715705678929727", + }, + { + U: "12594704408697480447977718642298556483366858661192216507974300210046934266439", + RefX: "9355656044690706381646646234435539528020065292337531507694884168933772079079", + RefY: "17381025797630235757166208980756351310809157410658037174942349647804537751421", + }, + { + U: "18876387659817777281007768203717070689821861976777760481257041259768679330683", + RefX: "9585540946442909936908366932901839208925167024359810871792254933012507451678", + RefY: "16619591760921523649980659278693750126940554431667413115944303320325443889015", + }, + { + U: "9038663774823575264388918507824684415126155618785802812010437263024265383475", + RefX: "2029316339417098897603454614373211042400440074043564745346363350930954160718", + RefY: "16932321422378872378480871013928877592485987558295204791254401221448546983649", + }, + { + U: "5482683607004755960768096640405314616423820577181054798795993963047932872453", + RefX: "11847921533523753858569918585884377463771504829015456516206597864979686333422", + RefY: "15282633427912165888808235493960089340765567473384165894313524410544644305329", + }, + { + U: "15075474099855384059600151256365162237404855927883905535949791692807377048576", + RefX: "15656228104415653560770410769129274194853274278008050683930025049679385649496", + RefY: "16460346690421364561606508795702792842800064656137527285655742630893759510126", + }, + { + U: "1036980750072881529577349189412045524243851151132177240312494171165776907878", + RefX: "21241319364756559480879407874669863842311309672030309988700711786029488404136", + RefY: "12192855724222991335126145742531310082351438048936493354545281185574338682672", + }, + { + U: "20851227594711521989289214466307049302176473612703011006245375566844618083248", + RefX: "237068905871293370770922948339957985917159427263179063520966908678095336009", + RefY: "19728337018660871777998244445580321842804607808646350990358350464457038103904", + }, + { + U: "17774302813355637414116140559272526660724305175073717177158707789842166398742", + RefX: "10619012794626806572020555870156903167040326246730954863621605092253743712586", + RefY: "19746578510988800636269407040278269964020921036191850753915147113862529942952", + }, + { + U: "16431197955332226597392758099184527840347006473407902983699508431863707280683", + RefX: "11029665477763927672808174125117434370662019074284716352189466002115655205329", + RefY: "8028793449041772672826019578795646677446109587754147174735978216521372200557", + }, + { + U: "19711582593190131625650137607814523930501298321861315439972953052743744970730", + RefX: "5219681232280446948248361056154657735426456771334806732539874001625646586126", + RefY: "3392827305316598580855097158837354143068211925241051118394893181200426014200", + }, + { + U: "18718432196030225796559954969467110138664705865552527084851219893135606042600", + RefX: "11672907733893697863692044304999693695487829860269651511686926438318004480430", + RefY: "11231574186030056692695970085498320253266249618881167041195738433724716186056", + }, + { + U: "11963121681964837861895179698188543205548828644511294743914578349500455997794", + RefX: "3460071538826609134249181663197016078615805823408306430810306866492084294702", + RefY: "8363105435015858451086428558580854600402379274899366314231626301101347326952", + }, + { + U: "11931297331814674146071734701385232795555173970071384272951947342200060581969", + RefX: "19374737054471267986479492181350656791464001489137848924553333419001737151273", + RefY: "4149705831754034175634242180680152150642728710368835205860213892318376033183", + }, + { + U: "5365018063018910079891130085599105792992857843221637072393490726977516861232", + RefX: "17205091607064179418091717148065404217263217598061617320483587372389865295030", + RefY: "2505832775348193971092051476746554734814057400675184804143339199495750071126", + }, + { + U: "10464000077766171402772880949201003580540512476931094297161405927923594951108", + RefX: "19494852087169166494700958388441522703321392288642509464087417758712324731609", + RefY: "4113306884224240479517192288841897789366270840531096989900883148024608754674", + }, + { + U: "13458525731585119909775989037787906374468803575659101995776972006156388527077", + RefX: "16981101722578526378649940608441023927504947034539874800949805244562467973767", + RefY: "12730190796356518642211377542586739154367132430894836618584598827929451266973", + }, + { + U: "17773247312048650355958673475107303746777189920509433378785029315768736126231", + RefX: "2583917994927932477231167287647380961256193554329685826146926802255082265781", + RefY: "8758167240355303805390302332417361220030955305628619705972322932489754560105", + }, + { + U: "4315666483889299479755067077409540325243188132399483903897221962373247102884", + RefX: "19753082807699405370725001697616027467911849970675020716737612939049518573980", + RefY: "10036108362114190534716726584969638060268434848506766908244756649528604004756", + }, + { + U: "13534503665854541544192437805378666805445154992705616637862127874929369406335", + RefX: "19483666845155839402433655006781979780614431906814778928743113360978901895809", + RefY: "13862997914453397869937982691460099551830837516706687385672970123781373462087", + }, + { + U: "16190562397010757804600277124815504112802588895285536951213572962328966906648", + RefX: "7743816984727267213942705995698207463840950870603025361429869776826859367480", + RefY: "14399601731903090870691128401775421356604577031686672580622900369639408460370", + }, + { + U: "8296448810691936708899324929071400837237159107795943292347613262499591943479", + RefX: "19344608151983102422541373946230727506646010660050171028493640618357347516967", + RefY: "1487187378313568763185237835106565540120001768929172489357796252266953535879", + }, + { + U: "1471321160305766901156460495901557186152481673650435373565730039330093036087", + RefX: "17028019905849409975153063251661300220210871048226764070169924357313851830279", + RefY: "4732942694650562814088812097360497459049061942946422719169134212444797917325", + }, + { + U: "2736500250204674893622145788042423106399026487053296538693870594774827916668", + RefX: "9085363488258063139620890567536489215923345617479188779824224761115358280134", + RefY: "21117139119168509112256908046691094817173015446854681822414899493711851081368", + }, + { + U: "727668084414273888864723409792538930467035590589771371254193218540364914018", + RefX: "17603424456019276228593656474120541848615067140996367026070690655978279439991", + RefY: "5820761141276002140072370584732392167005949885183191127702735520939843994188", + }, + { + U: "12466117381915702747694820954126310482809312294820949881364606371708669906954", + RefX: "2174867490180021686526326830445366973115159387811281580331494163092130154711", + RefY: "3910581584376548442329724459102515180498332754169794776373321804312676176182", + }, + { + U: "21420103166647147820385609693134229634054712028927861206630318569607208077427", + RefX: "3568005111399465947750111570162236289615093184138080421520341948184214021475", + RefY: "21884808999434576166712677368535737764039322109672213165631121751792899712953", + }, + { + U: "13704992739613971607343910039057583360273256361480632354696379046697511452001", + RefX: "7227335898101830103519080568903908705753511307464950322844718874460927231622", + RefY: "16882954217538996317048717274975408417742005498020542560537036435620844061009", + }, + { + U: "10047102154467953154808124822624718926349834024918731124566361658639769097277", + RefX: "20132294515596493249330105619740985231124732133045052624135462673837149872382", + RefY: "12617823334808167281392525818499975205160125193167032115914659542052563351825", + }, + { + U: "18989901187345945119140197263940383904016097630159146169130627797729391961578", + RefX: "6291051365143822955245186990966589844706180030416587891859156057897734992130", + RefY: "8548358826003913603902728514711888664352859497273706987039171746938216481514", + }, + { + U: "11096955779154971243392916348840920851295958335078223523657679741328482680180", + RefX: "11030887770696544700028951420695213424940860981148210327497235808096272213174", + RefY: "15377638979475795235740114076025732911259860903806186005725300503461008265450", + }, + { + U: "17394583031603626979330294362807424361896904621049550060307529113954728302995", + RefX: "11787523469605379701572597535217524438338780567703095806964677442412871111219", + RefY: "11007107003220403386327219260876998801552676156901499855703836808651079406469", + }, + { + U: "9757650012884878538286942707082460422085046747465521857524072421303095289404", + RefX: "17133317141704084755553796029294709427905982542442669722396871449205621807231", + RefY: "21330384892744050036483977791740044861344273069625372809109160541006695613390", + }, + { + U: "13758346478568048328358672745367972705743913013982740520358245183567573144891", + RefX: "16618659069896145298210959318834920830574548709704411353341979070051853031508", + RefY: "20769282916494541699803181144566468549639373880076035513866277035119599773239", + }, + { + U: "916113969332544975954674446914222449108789268238909700551144950096459929861", + RefX: "19900227822140818641821728148823196020547139793508800379791876041159372859866", + RefY: "20704545533621730015843797713100723281924193797652468064950459301814316143045", + }, + { + U: "15786556722737997801372350086618699576922142671079454632434697174433513656984", + RefX: "1148963463663540235455131891051358251304338279464494910739920187982999706082", + RefY: "13833972562625509449370127155297777692682290377308103377805342759371701047316", + }, + { + U: "10905294900669820324233102457921305918053694305724755861279572646910859977613", + RefX: "9798133769718343538157221556215296147601490028011277610885274586745838485120", + RefY: "685449551509819487805458393808369371385701181839436092935157063264771444867", + }, + { + U: "9331421314834173341609686360003053763691418564813802865288318496890592776531", + RefX: "5240553519178094522314024012601323806563605607895645126959367652189043407265", + RefY: "13634241565359301033555474138774356919886076857579054867797524991833068675509", + }, + { + U: "12561997308413992190432433836829665050867241842776233263216675517677417934418", + RefX: "16365156740205393905702116372676874253147821013745059480156418402824735453564", + RefY: "1069881770955925477599812150180875286485053100317480796321042798217016031938", + }, + { + U: "2580062041518819588791037802678249754175418055874863485446670687133295207156", + RefX: "11837115713548007834921035518493392690955053847022277657296179279667921711480", + RefY: "2150719389155443674717520675644575247705713091944812817565502659722096582152", + }, + { + U: "20421769964171755348898265039643744806430436776515197294081842752348494388967", + RefX: "14830094303097033767671999309799530531256759061828008514340360210572028537306", + RefY: "9670933564149234385411464277945562846530563847411924825256516045369844158673", + }, + { + U: "8510772353153717052132341119304684842170868208313377399714746574608454757321", + RefX: "2992978070126380722787328238147733310004867979309270489342119737101900964946", + RefY: "14130334643853175221375960803290399928227923760744285807689998700194827079573", + }, + { + U: "19431292470096284403291329631415187680782628275041386971810254400898681236648", + RefX: "16692941330770919324837340883163262416727852352324051564228699603380758052157", + RefY: "6243893007708130129568618019334224098407320012819899458750538889587754721442", + }, + { + U: "7014889148395905315080179777142030710133900333949898067465256617587779109727", + RefX: "10831256313069821116759956540455150299414455014470187111632523729453900027581", + RefY: "7899347777798650370025640475530892183989176977722832542362924035302733631357", + }, + { + U: "10859456419304832587529789186459408074878717110442951127960921663454200106974", + RefX: "1582474923702118623115572179108170840814728974959616491607160413186938801785", + RefY: "15308361897265531893423728997785956506285849318985903067757088559057557450126", + }, + { + U: "6786958518349970676290503212480866600571854515097985580656535904665295669386", + RefX: "3179627614892552082039109810553747185114792360989060452599591680570696144134", + RefY: "2267422712866463033384562218301868308280257005799558150107201364947591234958", + }, + { + U: "11845512091042850784450576223867719912230669586618869410551794830254706101549", + RefX: "2194990208306985477209616490273040331925601132992816543320438645752790216539", + RefY: "21169840494178967690585886102363829182171964150933865424831084606860170725305", + }, + { + U: "15678076035472170513341352102752488487753782904745311515914781488616896471487", + RefX: "16817903857099515998118166901115294948886232363185780205818797556287923789035", + RefY: "2102442071407743859459872778382923407221356298240389223125386488190122491651", + }, + { + U: "15896156479626033740351706172720529226067964141691423132678162951470431873761", + RefX: "16297501500639365393950110562920885496243765452426748499360854489636287130476", + RefY: "5770197368218148375659828694880781454201391088792001177563254215350127268503", + }, + { + U: "2303708629130882617635514444639334101243232666181325924732114309184826285801", + RefX: "6673563342133578314385356013284544825742399214180131882587057314910345305686", + RefY: "16878352364234791910528545641148597928464544126789519586628968890669069177201", + }, + { + U: "9580006782201017601390534620616618885406887566736400995256518192125995406409", + RefX: "16136254562664525627033457714818461051029271419176815896371277834727990560731", + RefY: "9203595300916714765548494692767821659933574716887347301067812982217911159487", + }, + { + U: "46442654750526271814954978825600044580010450162961527062444789436931068333", + RefX: "2357987846042676976889310861561276532807462330608146905204497656392985243963", + RefY: "13010592352750027984917025032752262685415788301775092129231291935476861752809", + }, + { + U: "2581158614475874114366848694799946550916392494893611947323053908137590330097", + RefX: "20562621969583057097846991928108787232320471167202713550567579594288159867457", + RefY: "18054792921287113603446100572877363825815967274881220356531586541678890170575", + }, + { + U: "6025562086086231456358063624744407467402131677337747721970324967704525212469", + RefX: "11939125818654021932918376830384325270575111831300714524462935870117301519598", + RefY: "9144116463935235781253030682460922682672862836686980477953083981809469963667", + }, + { + U: "3398505570507528601432728818253813531598891982070005248769731286921182219921", + RefX: "21800517965725432991859232521088007075841923542447726788685609902594595583099", + RefY: "9619318986717439006672557054804421895439099319945831447796104565633955459877", + }, + { + U: "12770627611170653241845125725431978888316917454795296105706152601281739978108", + RefX: "19441728243246990922339374348110085107462800380233646713380966824149963201053", + RefY: "19348301736880301760442820191185671140913218823191030648620363490855896101628", + }, + { + U: "10851196786423950527523826893260338164177182880300725748742546010900864747542", + RefX: "20365168240239395606428496018069371567234342620515801565716062836144088330837", + RefY: "10990102574843952755915119105097379090082006193330024608407230733760488612452", + }, + { + U: "20959931308333580713017171782245913294529755137837464019728037707043069377726", + RefX: "13965428133856027406809396124591954239772816737670604615320814467365834253500", + RefY: "10316824632932871850326334765000285659254247364313459130214624321032669081916", + }, + { + U: "12256734348167341317737047539136056398315094425722655080623952502142063252831", + RefX: "291980731647118458821601888406522739971649052067995080690614608714440385157", + RefY: "2937623887564667171507038208357422665560946335798692373383712037010741101547", + }, + { + U: "17687208429894433260392881422527451556252817273897940767357942545623336870474", + RefX: "17048463960814761640741502682701027248783728801497751554659712962394789941015", + RefY: "12296906829890942434359328516623965686645823948501123899031767417443317039414", + }, + { + U: "12872977311650677634041834325646396300532218452258701513267104525836552254666", + RefX: "12348827118774582093206293001317361255645220293585574605738715896564265399542", + RefY: "12840360772349448240645879061834863485393716053763404151463305803648950795444", + }, + { + U: "9480212011605441336942618438098996544992447815166796974111466570617607344203", + RefX: "1076392728922832731955883208548443287803397012629742171349385126830473697698", + RefY: "3463740765348953242765763974157894974892132255030663808167058777409372826017", + }, + { + U: "19420008412294270629436204600438387172952001378482193897394283183591623467440", + RefX: "3314243136478563986159530767744955024991751457746826214792608755680851179400", + RefY: "18120330094674311675908737009972348195155885223464442176386651003571599778348", + }, + { + U: "15709424825765225912247409574460304083596808095035498600972222772471091457096", + RefX: "20827574666291776523541443290587311750145592936406216019032268605886162364654", + RefY: "10903142326299171715994254891469133301680099715910572005726148290614594600470", + }, + { + U: "13396965570357615442385057973245656910427513335556806969304718870159255696512", + RefX: "13773442336258551079708526715982182037548986483830140303426447148383010657123", + RefY: "14142154133136411574821500835148179703238512215133361821989603839466879929784", + }, + { + U: "11917440828076976245007461739891471475930747545240492321608919689333827596152", + RefX: "4738530730572248787136150504480401895510574614357099209814297832057290667338", + RefY: "1441209695246163518983482878468844718661875718930873811633095225829786136688", + }, + { + U: "16686264202827864250460461154483604839057242002089292358544411416908808110130", + RefX: "20569333520021312365866353487684059641987349660027847258488980749693177963633", + RefY: "13217440190463032765003990685852544300496057357319796741768699673522251450196", + }, + { + U: "7085445164456896490243925779088747621367950610430008958063989520397111906648", + RefX: "16020223459275982412482523142093007459686407260600868940982461303493896901840", + RefY: "4887583964289155918703776382318738931693269846593748511201536000939860367036", + }, + { + U: "17814633750647392071628205700466285567705331425347772409787131703625210373820", + RefX: "18654438123051122779182683654606822573493828357819757479223794212294769706835", + RefY: "12380101535186544692337445645529154571859629951081699511136611049963177935118", + }, + { + U: "6432586284747885075379576745617616993895365315247038319867570054377806957743", + RefX: "2989617322870902418989425140039023586494730507620380214837292236833635055194", + RefY: "17017688133322660722419429125427039469749515631890198552870498959469130520753", + }, + { + U: "1549081013121499632231697963994069386858929445186403075222640696156167577421", + RefX: "20695400188715718085789342725620186127157053681676416735681178936435194220473", + RefY: "19724403932809190856675130718221886999639982353127313069784648111853089006305", + }, + { + U: "1229705266283546608450867367504124062534590058907092858426934325753439713879", + RefX: "19215538486345524342658301257808951957927377036451828704836681862555800790707", + RefY: "3125871529099607321192538201111534927404394210306598631577947409352279354787", + }, + { + U: "7372923521180603765728351330579021841156390242288593171517914653676243183490", + RefX: "11977182953212143139764807379231492838024744616286002198182447690462278843098", + RefY: "11805247755533769049174111703032752848744941235918159034763545513957016835800", + }, + { + U: "1973719413934783180507895660760281964912011238925592674015117621565404029403", + RefX: "12596845363460685376243030716089817115115053469578454503939060855120401073380", + RefY: "6311118544241014989615642305400855167700817598120865255873545800336051390717", + }, + { + U: "20016290418415151061413028173084924257926759730124101316681640734193435848886", + RefX: "15604612600408549331185334028858910059014961188173968158222362681161716912685", + RefY: "16630458125253721668712936710354759736752256188056516889509118900045351140524", + }, + { + U: "12770915918358340877220234419298405231031426451590312383100319683107076314362", + RefX: "406739459179184667380569222833006663441134083389800055339783940066080527144", + RefY: "6778282951953689593005538379244705820739489077781934430644375938955852246386", + }, + { + U: "6356041313528966611407374813704698130702303534495891725700948182157123052461", + RefX: "15683167885031658756301623740811057086835985815229250636404273357403968613951", + RefY: "14277504498399394378036535126653499233795285260384437359535882693546470688689", + }, + { + U: "9883337266357006014355049564802219265268709766881276517894148171636172989022", + RefX: "1851379626971956638734451349349147636329598808896428199632892496895863787745", + RefY: "9243121763791325920750907039024698094941782479618689494385059931970685869354", + }, + { + U: "2108929715337676191104887757530581652822609471112581887922572478795613105679", + RefX: "19819565852786786971656919896069491361807867714852109363617977899483313470890", + RefY: "15633603252254133047201807119305263172362647690199072015418328831449953099227", + }, + { + U: "15977540799194466010291784544142759965180118269033101269874141916601682151057", + RefX: "19182807314864437874963140791445391254709702372075944017571248562508610777371", + RefY: "6452442731430900369946604730768635436593574340030442876976599021492861048887", + }, + { + U: "17463123175516728959697911518531411611379201220743137234217029422131647467463", + RefX: "13014326429202858877617827128475248640099505356781244464207758696140237419783", + RefY: "13477399497700025290009984421059932687749208264576628243517694877445967697427", + }, + { + U: "11700449983465457480214245401274232153016628451151148382810835223838541515414", + RefX: "15659721913318789049641638765160614276005875920608660539163160735529948096188", + RefY: "14176275409935167629867417678253447492511272327090895027412287542342214537462", + }, + { + U: "21465522165169559819790844180359059756013961358720484730117292212873555420752", + RefX: "1594678464410104941981656328318119264058093686103163477552573893586718292702", + RefY: "12615941588229160192697922236746019826843902138391928939479300831862274635608", + }, + { + U: "13441169858716866020357028297008032769679468203516098103462641949581013150740", + RefX: "17020845801275580016420715048604533556796700356345134094777413318831349699751", + RefY: "18744503313498061401066332506261994897389814997047822857136995533343326609454", + }, + { + U: "20636259689987202901947083473614012938033615292097220641804037087057332909000", + RefX: "191820028859917609224513340814128777153769054702514474598561199751899318380", + RefY: "3147242483132172507358730652325876492067793818849710112509251047502288605370", + }, + { + U: "11086297961953667630999737628910710324360299421233781058938106269752448730873", + RefX: "1169116376781230736568464012451704276952475110515454954800716118386447028829", + RefY: "12499025167037673760238365876459092667287823199566920608955654940460118440841", + }, + { + U: "10774252799632960629008607325326868694550679972025917884896070549970648313671", + RefX: "18805440035962323315527962258072021669166271339131923780400697152921390998870", + RefY: "4146991164407469329172066202273116347905226254558791200446706149136896566423", + }, + { + U: "3567626550473439941455773279751560278054847772172408187380291920365458137876", + RefX: "19600779539478303582517023490559366360426414284439712786921590904957805157279", + RefY: "3692705632361790337272361422351544307619979365592223322411164122095079417414", + }, + { + U: "21294192579272072001014182817851320037741006469334440929949609039436051154019", + RefX: "6321952391220814416963494821489144208782006637084294577452476526521643855798", + RefY: "16995857644282722531176386913110533755082131181832395195304319921582337333773", + }, + { + U: "19779393576585803024597091508296816088995387010400193625081492016174639017003", + RefX: "19923933680929556070337945285301591379878760456034366536460182485383486630162", + RefY: "9589663129199512118802380181668806814695445326364823971628699397684322467107", + }, + { + U: "5344018172079728725661239507722158648240767261715736795259191723628937270885", + RefX: "1840233163631425936288999621594556847635644680347404007445834122995101086096", + RefY: "7938600947216722712005286576345033928450563344125377990563868507221933198099", + }, + { + U: "9097657994848879589565067194143562100721643327264865226798514365055110980716", + RefX: "1058532602276313789321990405550754964230010428156049592312554021688843934016", + RefY: "10283748555974731100562929550942346908540251247636365489024522121583414869962", + }, + { + U: "6779729378077536444864293989974284588948581801273526978012732758802689847459", + RefX: "4903550517655236156893266273337148146588941577565192467003881639072231477375", + RefY: "20646526685673924689211516440922059574212183122549024551477609671147424836099", + }, + { + U: "3700372301835444604892744905467397940646065116019260712916963162419970909152", + RefX: "21098964429266390379503002690336508970254668621473636678856501061110263091484", + RefY: "12124066315678291126107113506176565869589411415885842715976473925990299398258", + }, + { + U: "15555230983802113511236894896173381850481931843258060015589188738112568147744", + RefX: "1451301337062651305891726999769664899719529643532217768527359967190670732818", + RefY: "5379365016113578883810833949045190631158151524534210355524532365957616773784", + }, + { + U: "21178726186569867092514413714733665136405441642632524127634004423311910602583", + RefX: "20702170820899226642563084715088959304272810144050818044836894214261886524356", + RefY: "1686088118935101087574880076493855345960451630124036935784137691833370115713", + }, + { + U: "12327591743789935087804416423215034843852877768666330302555199403825194296824", + RefX: "17950582561998822281238931595480460370393615699764407220688454613436812647143", + RefY: "10723985466582056577673383062149980976677564110938762503223844576876912125230", + }, + { + U: "601158499520989670995184347243676976274352040260085521739231870292668275626", + RefX: "17445924415272335950633923041786767651596877624413800441319364692290414245556", + RefY: "16856181121626114204577413304351694735468906483776042366743257260562373251422", + }, + { + U: "9750796599281586002898158249962319586353742543202206520855234989110084068605", + RefX: "3246771117295043051311085641932531476027372855922234401172190125883230874358", + RefY: "20993339124722266737215759392471620476752340594451202696452102170473942591067", + }, + { + U: "16153934375759504742248948520290482672914837739240613759281056770683799711218", + RefX: "12945001117815382793828317532269806019268336081016694857634814836555727658392", + RefY: "17618784119044673515027572203209400107798322038216755956890099485686423587502", + }, + { + U: "13205659190705371957163294070781035871903987738331560255343581081790141881503", + RefX: "11987584182239435624871016120727008768832124050136949185611189247558265161880", + RefY: "8782521732298081699994949971364839268982823547358433132071259073136652545307", + }, + { + U: "12994748475756794943273396796713133049384854037583270739856878088574499342560", + RefX: "375678334019766421010059173518085944567780796041382789791243143450998934143", + RefY: "20839307386479968493387372221654225898430173838981935279956595509063848057864", + }, + { + U: "3099993888415290415879296077823773654846495776657107324616947199403708006793", + RefX: "10806511225708980534950901808428926389884051859271869278647711172281063905962", + RefY: "434734997798806509634180195575176797662267872226755633508817912150072346729", + }, + { + U: "21290796960688642041288593849786251608761816839217410316339217302665892287181", + RefX: "11389579315319293250093398748135842238667813053691368083279513848726563315702", + RefY: "1632079102746219403989249271699473122974061147342369788031822775792817813559", + }, + { + U: "18800847276762153140720063463535116750114396794209138367452609127886644686535", + RefX: "21621392680207689061686758622360261539016367581012309037750026382793572676392", + RefY: "20452529330521038446367026616428328843420454871509428556941028239098930197255", + }, + { + U: "12352350779764300112363178445229351970427627032266216713854485955123300482149", + RefX: "17498299000998663881839431526654998628082241812676068925472569562743961478836", + RefY: "14958008319056735499690068748847010995081738944287112386003574610063529596891", + }, + { + U: "20572320997250220104621700877151743686175796742511517790616984411818970593896", + RefX: "13696615322435485841313464839509388110835652219763307799036632583731319009220", + RefY: "14189658684484109910038786805461981088516577461774209880333147067660403039622", + }, + { + U: "16904526620569240160885546845608342706728353828645587453534783645751664897413", + RefX: "6330490839674745204747577838951902328960906444477494300723140325241203356642", + RefY: "7874513261929689055969789496627902698722183343527474551379461336030978730659", + }, + { + U: "20293362810465670632902409378509172087755014295594394133444107166571508156706", + RefX: "3576199628711534318401281187847740461937458234202273965726506281097392488059", + RefY: "9990311221566454795223124749411490070945840759229028478613366776313618126184", + }, + { + U: "15888448537271885555588055598447489567473312865434796627130166631232321256891", + RefX: "8618079052327765143820842758287084684924372403315002271997909783385058707957", + RefY: "11201614341376533569112312906908849578420336201389834908063588745447190958971", + }, + { + U: "18661918522385922021201673331740852194333453863720882418780997337822783623065", + RefX: "5835389969466355700027291743058631156787436217334715582277214534934595917532", + RefY: "6377735340458879539877925306055315185918737728475154961336152490631559435115", + }, + { + U: "1671131946831468289444264411403410435887460391211715204087586471062426095688", + RefX: "11263272984706940951270575866290272931407561184326410371548547345135687553011", + RefY: "2502227267351152313596233171298856663942470374064371319112062813694563285082", + }, + { + U: "9938539026254756624651034643249554531634150865043957198889233508499368510554", + RefX: "19656666856020298568291479792336341489415949532722167558764696713507934349696", + RefY: "7778600294817032305681067048628066267516874179509893425701298708616807117608", + }, + { + U: "13839963475323668595620438825743807297150627711930511839965449589129402194775", + RefX: "3684754265710515392969802244353785437396882999439218002791805005266601737475", + RefY: "8491907450003910471542306055724729165541389778721383912891012537747505984529", + }, + { + U: "3038511435081474984412418612485443819900831354953752362326686878336220441461", + RefX: "2649120973520896480233669737265420567359004855195126669854496885434122055054", + RefY: "562594579683634185561718902248568863451252953739781781403664052472720700141", + }, + { + U: "505318273269880113818981103212899666729310749747249304211134110801832904655", + RefX: "15003982791204538043742904806397315038545123118535863353463550893250072589949", + RefY: "4244203714788864396514221685041790478698961726268559585777610804430539732653", + }, + { + U: "15091112701532381752916714491110920720532910968689947165816403265323297116102", + RefX: "12943126054391987729698290648188416467505264888697087812478049703306989288292", + RefY: "14970023428394395316280941244004804551618766832490653220275047671757787460044", + }, + { + U: "18470536699100722901351188642863296963904850967558048190398257196592138869667", + RefX: "9043346805986467832218993091752746942644122258770562489320590748711147988680", + RefY: "17552550523024036265855200678363300809458971845098478380736827525934261357939", + }, + { + U: "9064189837244712666314511049637971006868103564361722706340363190721883668821", + RefX: "10541923064828209596963111758224226827063231695146771784477188348536849890673", + RefY: "18333957630467969520835790960644034512388376930346400942296696860709321143803", + }, + { + U: "8586945327741683688124288728963801533307234017425245966651866080786898407027", + RefX: "5444607019401314753882473864932886099077299012782804972232472696325941040404", + RefY: "11039694717816995794255046673674198914732230065802224271805123331379850296359", + }, + { + U: "1612711191511098379724818209661025322100607516964610051079250105648700850567", + RefX: "3814283983175916193863473898404699688176176494081449974427908465703551400721", + RefY: "14062324315127462856305022791194119257780340261182495029677714029996790800819", + }, + { + U: "4922688706192641138499744709521042769579150681886974120255907639111926350564", + RefX: "6464000607862057190237892779851686261956849612518423074299322985450009729782", + RefY: "9175266835780975193920953667677889887375908862183134343015743405217197689630", + }, + { + U: "19072597669833867401762609616334213452977780808247769714875272969009643579316", + RefX: "17468059720452163525234923026712694113247436335229373375671548243343737559315", + RefY: "21164188991159489437526952768090851821922005383926698975273123944827427754244", + }, + { + U: "4748412141485491733533030419574045646084397577905880963241253612586083910277", + RefX: "6218680910391262579293361667258650520968176024303989313868059296903170824929", + RefY: "9678816728741547899147638253374126318237855430472598809054837312038596554619", + }, + { + U: "14285738783542150399232148932044888495537724337840416649459543836342481024996", + RefX: "21743795738163700458615204166237039723111399682246851896969352014127756700013", + RefY: "4813499663315514839864287246229312262091793933274620223328577804503008391084", + }, + { + U: "1746306277127671132426981231689840563778943383892925216795351361793998356018", + RefX: "3537999817943562689415555635436292402058550692358359257605004535500638243977", + RefY: "5155455056998349577157859575400426498162596747856721402547160502509329962136", + }, + { + U: "14591098113154405794631420750164356190072606981041834771001950002765504843504", + RefX: "19535824940426499814868325770364671753152278330715112038082674031417826586820", + RefY: "15440202757839353582301392798496869365370962607972005214752130870039490829322", + }, + { + U: "20242357335533248613347743253263490736603126593483994577583201962294633247519", + RefX: "1401344535570501953050678314502727166620598886713806228222228070737154757382", + RefY: "19537395211752906209639724521010463436235193440735439912433196399647567182151", + }, + { + U: "12625177392242568048323664741470984130128234782880954989884626950956638447975", + RefX: "11235858010760342766219205231136116130001739879125905412480541876834292611198", + RefY: "13665979363870993655663093916731409830283408767598889976457223038719259417031", + }, + { + U: "20426744816963791532926508463059583738613027959066473541600123986234958512944", + RefX: "3126260815946649194879089752967960548444794839742570635699326508658799557160", + RefY: "11867277979039475684503933599230413136910174814497355450280644575304660564514", + }, + { + U: "6871586302413544244309444174735739095378641566483030415964025442190803366440", + RefX: "11121646730468216563697439409756989221794578891959429346547055169155512458674", + RefY: "18863412215175785505548345418609156674472886954056698470407751255502685580316", + }, + { + U: "19037648087283186823238881667657328608979851344446595647873914468478332452466", + RefX: "15740496685995498428154391633013868165455823164396809309530887160505178762822", + RefY: "6163339760507613586641808035227941835230093471048645959181707257603901121988", + }, + { + U: "15856910149521657233122834730024794271785963951990539629653907756405269347547", + RefX: "3791230060666694343007496052750738933300712198266228518148987892856583254815", + RefY: "13068502333452020652486731962526141896323049981325256505760291629349262500915", + }, + { + U: "15231525792074588689169119851352219789762392213769546108590235488211126959369", + RefX: "3981656254896835890075143793657388930366390877409133347788975699055145792115", + RefY: "8460491140923581534876851470300717830805938374054481460899078479731922088259", + }, + { + U: "5081656202644367198667673127806248189489033741368251225180387751773167691579", + RefX: "20145360541555984260124523484071291032558954643266251093060182133658740858628", + RefY: "20610125700551356723914017640498300683562842970770999190238666228279526072243", + }, + { + U: "13529075773326328840456306693540870887934840731128336800814393166796833674195", + RefX: "20483833576685654055608972398596562722017392730983972263205691973307971339184", + RefY: "7810624941493723020180155676143201144007264598273086870133372909025075355755", + }, + { + U: "8720825375738639514041234521307451661107593845855981536939702845671614736990", + RefX: "15131709100957650099487813219424422757322101099836850126535636001330297387002", + RefY: "12704873943363002439422863012243247750677635547048426542811186957612475787398", + }, + { + U: "11383672391168186199310828052697219468845277937993847219298735709315951399976", + RefX: "13899326740594293788696031968201045547029406388582842010051026300322987226387", + RefY: "11402651862705852317321487542656508363032938510025720099429103858601573399728", + }, + { + U: "7256528423779106511207284736529537845191614700756579168697632938957969779410", + RefX: "14981042441541110712983254368750531746714786893459028643428929915428761023345", + RefY: "12168539730263040479682104835107700299047137938822720321013601054511204697182", + }, + { + U: "20157257616781005944618527702542021349391644273806838178285516139677188223655", + RefX: "8081312985337971540892218643511289400197361103855430823861618953297662716975", + RefY: "19682211411412646893342334669432792457435819319982953126875863972794763411225", + }, + { + U: "2128583818118041174508486157376896402494563362584923783425716216389059598277", + RefX: "9204872535447984607298143064677105700012043473897640842952724559602701580380", + RefY: "1183450718175860130075455757551296520235627901610921597440446609998693123189", + }, + { + U: "5075577792475175794538524262073867825504517415223792840559996339810198123271", + RefX: "20559594414729776227471226358834817114482387004835815679149704753579742964076", + RefY: "6259364542283013278224813281989778270951553502276942340358740823199213365935", + }, + { + U: "5974586624162823269726002389313519137873904852794720618361124699742177771903", + RefX: "10969106835453981684147754441498392652288487804598692725218637344679117327607", + RefY: "1265597168943727452518709266376249627353408440399971733055281656512665165913", + }, + { + U: "11249089185662685730179357024453925676545874696376426988694137407086974030174", + RefX: "2847555481719009831061726076508887309831037321160761734070454340883430724914", + RefY: "1941704755343017266769992611280440839749256786619140907192280010955782147886", + }, + { + U: "14422806066438067029337850823635421101945925015496538419902256544213012595565", + RefX: "455038208449071964851773834983924402809375411609139662867378975409613730946", + RefY: "20647974343774073859360589569991987817931996562041242989303917172987279215023", + }, + { + U: "7679278997104899330181868494856781681828516740104873694949369034470656380755", + RefX: "20007123800918214325249747287861263312454013396172458295938291131640851672435", + RefY: "15822153053387281371478708802430669537078251576675646948448573224152723252305", + }, + { + U: "8720372211165533739618401077014860492172519836279356799911606287382444089229", + RefX: "6710618322202781973496548045336587446242605421669035002855565601841831302428", + RefY: "20488223811856138574533502556961463126022720381911993321370094289995855611569", + }, + { + U: "8324591184240016392621973525237537996806587788782829904086025993998909570226", + RefX: "10620380393596104108162708467177455675260312519908837051297927502896781661818", + RefY: "15863297533478369517966428893335968076621817200014157172875675163740430516580", + }, + { + U: "6816179227788149011033719523729851155419269319459450751888627598777060505246", + RefX: "10098958833471500013618175814537682906433304200371577304296124622373974413889", + RefY: "9768721453386130396825637812361316758180531273601936283469537116852900513118", + }, + { + U: "20201036249605041335002245756627641728914323605638175865083173623955245741436", + RefX: "7751698104388496582053093681570080279235060926293803539783562863017931705136", + RefY: "16343255630350380968042219079211588304699917012815391895328290710157612187478", + }, + { + U: "9914250189617006487105104732874871692103129118617533786350063179299645470109", + RefX: "11874868260746234557422302199417234077974451820927953896882102293734345612004", + RefY: "7555080060184138393788325920718194164617997515452819914090067240466365910705", + }, + { + U: "16507395720500454659501668855072151355277243215026343643878627536912624680285", + RefX: "20802871930183109219294692641904013929958622379760561195426378537075697624719", + RefY: "21613129182816224738096010692102859056852588934202004452779599638011506806383", + }, + { + U: "12531513227641656730461794932946906560436323845454101919577045112997645427474", + RefX: "8940998851000828993387653282984336220985761269170426384015481950850235094806", + RefY: "8738895263610528558444259093997141343743941843232084904154279931396012236408", + }, + { + U: "1875594151271077835481560357437221560066534408863336825358504245561812927505", + RefX: "17574841546444503315112777038989756583502518165190641294795687188988839008796", + RefY: "18337751159608590584853225591876568655560762435274312746892368222209435590575", + }, + { + U: "7983190093478184616138684089232337277671485476103563899736602512374305740750", + RefX: "11530022606191263370926297765177709699235543040938574030008662037858774831562", + RefY: "3726388454407872836578583575658662695830728139183177600443170378792410576170", + }, + { + U: "6909615688296476520996899113089690464810044364086330989545314022570573784878", + RefX: "306520827839672504664947616141202549298843569001955237452695065628382182829", + RefY: "12929108150621766771121191262322198483223083576458043097616262871808689208192", + }, + { + U: "21809501801440607047926124870560843212591856577112363641773980490855739026118", + RefX: "15369694455126483083863288689232177110859471718853475210851694963313848151928", + RefY: "16576871086703922197610050752242257360462990928463811120396005522536240555292", + }, + { + U: "7400103575761890580309234720828965666907432014400026460259073067568818185509", + RefX: "2568197103545462794055697112845291857379049303105513670753079165706048482088", + RefY: "6498030358978142825666921276620062703707731080845733071627718092684244702403", + }, + { + U: "14324874074867869869103151756174117122238826821575099546036119874679678687889", + RefX: "17232520332908333814145152175181114117456996612480812057619901242943147773393", + RefY: "10575271339106344182113980770365785273363483112043585777948390652322364793577", + }, + { + U: "4555966652849373649218502357890793263492842363901719991516675914062973891406", + RefX: "5129683655131756498997328618357486824740288701540316659369957472197207695806", + RefY: "8059857259908148027863221883169261160123280109786287968767485058771126004856", + }, + { + U: "15751997934418000909037484728581590745824320209765976033097526202564253589828", + RefX: "2093147490324888340622715009803994157327039345133349529202923625916383363287", + RefY: "14879964020529880540394916211646696362277919602449611087801949802388317215468", + }, + { + U: "2517224991281237602590743573461878004578028442327828790103759092818479870725", + RefX: "18370984339347864814711759367883391824185008970139581184283851355252398179902", + RefY: "6843614191560286876958876368307026377220003494895099824332165512369602170057", + }, + { + U: "6215113748285972942927243371458854459763009002728903732621472538715495217879", + RefX: "19152627215339049459439645714848698162405784070195373638277401698332157796778", + RefY: "7106357298355005786114175939590369508383630230757821658859415942527447905355", + }, + { + U: "18105684366845956455585241460782112581296718050036471053155181795541467495737", + RefX: "5904553627440189111583337739148779901782668589384782732499904456338866174278", + RefY: "5303613368779488866577398948316315285177073585779434499341036414349332913135", + }, + { + U: "11326743656032450356901888264778421555911159902993644343576647777756181717229", + RefX: "1773140368083031418538485250981350171660417080821548196417866444529497446733", + RefY: "18850674685802507574502852297370577756591450388714298804785763202204860919897", + }, + { + U: "14078452532214035855737923731194072159749800568968165863635841286963271104594", + RefX: "4055407262076233404236881926916162978065776774948040245620528670455590582091", + RefY: "15990735400223676357869322713437735772791743450196998931734690822469209109166", + }, + { + U: "11900932102260236671994239382967660956460718153855137213267466715870370070448", + RefX: "2048022660416351773434034166153937854747078931828775322645236787634294813328", + RefY: "14738549588975164462373217332291606732467257689531467296645906411184719805514", + }, + { + U: "11216909736026692807025743937492264486476574492996481437062337415829597354981", + RefX: "15137950584016780088845977327700231141639283116653877639852354857496180438712", + RefY: "1397779678031434502425093920961325492319592947841169466057340649703634848439", + }, + { + U: "16735861797686043312469927428886416658963055243240707350821168509205733209770", + RefX: "17994501973641337716973673161224189133319448689091978442533194887549844663689", + RefY: "12233855531550197397983660778362509857280092451478062283575655502405401197336", + }, + { + U: "13542230045836608240167571864835482394204747252116658765817329564999833879693", + RefX: "13696408855822582016504969779270092830613248548840586943707900362760983897820", + RefY: "8554988628481053891782873340887095246548014838868090010332413867850908273703", + }, + { + U: "7555909403121936648307541962371314709868388251436255035730244335783027875255", + RefX: "21784067594618624665272803624210451779613082177524842123900698580441989180690", + RefY: "4719084031640153753426132034967074780031822001528847513922363820072636195037", + }, + { + U: "973740312723066789751595624865158024534584949362444443260382095575237796122", + RefX: "20173625415285773877931227878128457545995392329841746673839332782001033035262", + RefY: "2802586757290535761549047326064169795293356248960175019621917614135580747644", + }, + { + U: "15165153942849015278171759493574892164421127792170848147750105755271803563885", + RefX: "18146223439712648476507402714018680518508220338420761290694379738036353677406", + RefY: "21304540461161167393725936456310728150509887864673800746067656340885492084597", + }, + { + U: "2452439345160384428419828873059172086357765401427484862216521619641247294797", + RefX: "20625767039475645229366327646441190132785327422257455514246759087627098587406", + RefY: "13023671960654015213163060306828735159885762397897863521293926727607306576167", + }, + { + U: "5658231571967154770955134734881074904775427399986967350756326872435433227305", + RefX: "16107898819712027174940281313624174196713966211850039136651222608938686170714", + RefY: "13611732293502940532849212829561406498191445047236230006341604939133430581607", + }, + { + U: "17099533324606523787341159271719126947102591598194316950395371155088535504617", + RefX: "4799852305365742722199276914668299834216058886767808637499798790988189597076", + RefY: "1486658501692076944289268748501365576762830300427443636751600925041450410173", + }, + { + U: "20541353174131415550714298933253620188798621796649681181085398218272944065308", + RefX: "11272575115275751636216163477561780120300664736599542661054559952159833196037", + RefY: "4114046198547832291489208177430443450172900076131193296411448428048246083584", + }, + { + U: "3474958082348822120552374009056828814189260656225921779121985907847107886531", + RefX: "1664866026928970842758735781319515127340502471937228604356208890969101484102", + RefY: "3929191146163530163608878230295322764326196463434341459354481332003529745921", + }, + { + U: "8960097311087500207738762910914370209605064457837822306508837406190874258356", + RefX: "10940446704633763458507380526758776993195501853007234768883672411710277913017", + RefY: "3674757815047323252180576390095630319834273524767784764135831266281489616604", + }, + { + U: "16880666076888113717721864558049852200135186780589798742476611666234866057773", + RefX: "4086065455192503603941960867922113205863479106382021572315855780452367755027", + RefY: "12439480313919456464672343575776337554702443309054803482206611538166323408529", + }, + { + U: "19003637980508525309333431857082455897061235243702175136445764783869964993639", + RefX: "18953307709111369482861101345054634370327790247921413165070330417032804993411", + RefY: "6687624739308408644536182695750233035884403493546014089156067016031751653721", + }, + { + U: "18826058168615398216553707216574050300919308605523952799620021274963484732794", + RefX: "15348290151088808798221983034247393915090317200420248892618328401699503029961", + RefY: "5631846712868890374345585353564443310576304516094802121133604103599910362516", + }, + { + U: "9252284053357705678522400952442217296327987732199788148755849102895254203905", + RefX: "10180794896326390809784928945889884130784695321695661568521035743186946456883", + RefY: "4229391628207817259227579471739699162757083455954657084428855446787109487357", + }, + { + U: "10054949453476248963659375010725066149634286667138286912295927154677447003554", + RefX: "4013439141696336231908744334196788481723902322890819946913749818770190672375", + RefY: "18776614935918266251132855723300713216977422783886876128160624264407819381054", + }, + { + U: "5980219326276475869047486136352707829683803504368327697305924622615136451335", + RefX: "20919553875155330167626763030167935085820545091402883516013951362067596352475", + RefY: "16762488932563813626176169230377174974636383949676004681744446433087362736109", + }, + { + U: "2670499452139026207523862632773076488955916751240935781668123058180662032188", + RefX: "19859177221722406513530830224000930074320098235529963389815528834189699864948", + RefY: "8297881386719816783374009377675663400010990370908624096417624142245762230722", + }, + { + U: "17650546572231285299944397230344922173208413561646981115794644242315492412488", + RefX: "15182117913178984967681680029376944913370430551998656542389672039101873003090", + RefY: "13986968588980918262045266882755709246442169089876566348075702446710305790084", + }, + { + U: "15413843445971968487572382857010316306750870409671633160923046088424394268882", + RefX: "15901210782343501630443835429166165307894367188894750551359340639835326948295", + RefY: "11382645141308488488659899341464042939570363600767957440896217983991686033968", + }, + { + U: "3148671088201643471145713212110661463673431104181801777258339213632016850274", + RefX: "11198030986627742368979898299167598752384460570483862881657494399527264892573", + RefY: "7271457620862755951454220769853746054948770483566570755221823533361301145492", + }, + { + U: "2567333690883703293986933184036823385490992629214982204267660225251918824576", + RefX: "665141069777689132677091547350682963020271525628338239828423656656525980052", + RefY: "14536423676048089248020056982563675312157869667930743532944718306932231608022", + }, + { + U: "18085449618821422886315198909309357354667215444857835495961870510631362652746", + RefX: "8470397350625047864108357135810784270017585291922728715709122543217177472637", + RefY: "7993903871733645737626200590119393786930434470621047027828163743877896652206", + }, + { + U: "9861679799302067733592839175614181812160741538306619339395806071684453662501", + RefX: "1605420035838051542574738838627210398467928965524454252638716965717591616198", + RefY: "14777317905227791512717157059853066642413831365241049036528495506643267736573", + }, + { + U: "19241098137388807635616960002991885865548532981857234582638864147264862189119", + RefX: "18501051161524520994702897290036900424445460855680679819115133334212595063085", + RefY: "17501812249476663886224624624238793315981638651173990164232008178362019370953", + }, + { + U: "8098030471418044493238305258433832822605480948693676162246400167058151250468", + RefX: "21738707416983936146841163865210604564597397648278004940710011356276947832161", + RefY: "16738741675280763881172837514830269936124396866674638986210295189348802222046", + }, + { + U: "9537130188057035084804356119838919206989152238151052505443492349353738292030", + RefX: "14848705771811268374911460102633249553254131749552106002680513926656631955763", + RefY: "3514654390925925490097906678311201726208856448392881368217495290994512556274", + }, + { + U: "737990211900337676084010614928039861218461125177501428661135646823715791262", + RefX: "17996168461598677909020849219593308337479216217974547794508222907849387687477", + RefY: "8651392127024961195177234850762445095834107540849982790643927052343907198812", + }, + { + U: "1839316891470989873311674131747225242664258766615700573200854536702483030650", + RefX: "11668944006587506005417571146371909955074431744929074359024333084738969392578", + RefY: "16445384435295961683277731125857204682567011141902395181108528503519636910010", + }, + { + U: "2894756763891729832730705954122582617136867316223384949348379873829035564871", + RefX: "18848500883636624119361133383123847362837752865115481026206299706884956452359", + RefY: "17161987489805662353724056644758934955985156661813893625332615400319825125435", + }, + { + U: "9158478992608660191459827675996478160519604499373864451950784875852169595210", + RefX: "9540492640433222145684839933703951654337124273790346721833613518927716569106", + RefY: "7627857781615030535167392747494311296266398906765860438811170825458609063186", + }, + { + U: "8458777620974120856878698509708532191250578446312990764447518970666402665247", + RefX: "12010628939132050795898037236621403159862977776225196352511021195445072339855", + RefY: "9284475999029888517560590274279768919718030893428572590026810052966925409919", + }, + { + U: "19809138121129133981588566694109681244150308382772775559912024741574962827262", + RefX: "11418369873349695472178954028460331645851190637854871436298263794558625442434", + RefY: "7170319356517720121944980116854464437986397323235374677917400707032479874792", + }, + { + U: "17422662243029445952829460561263999310184497460702239480172344382609323919485", + RefX: "2288787033974474694404368345685442539575380128915893306388878128959161164797", + RefY: "1808068935145141655801529671586893188205024628750716889447931766718289176025", + }, + { + U: "5761998292276190895886148247319248817750584854332900040737621425522952669133", + RefX: "15438489717530459228583291412631169870533543905947929632798025594180566359410", + RefY: "20668005291514428240712995861374896583647939067334153297750221808784017088021", + }, + { + U: "2812385664448146852199576103807772400043533378060739389721324195547930978855", + RefX: "2477238712670282129141655688081531187800877553596115204426612881467596321319", + RefY: "14642589020341871449259007796850954569185191793556774488323867635268429497793", + }, + { + U: "6984170216464649678308448414023715837256591507100986773332435932122285637833", + RefX: "9087508544775533648342030858978150843448842876505675678365171854891899933972", + RefY: "2421230790773435235949061460059516411004642526379860763848377518445454091763", + }, + { + U: "14271795356007401446614628749117637554816788007182732075908119300634594392468", + RefX: "16734904704527693198852062981297862792060977383529370856522257562202961139369", + RefY: "11787577524636167745492458650059730423831049341734503499052027631352554785172", + }, + { + U: "16235292557875333200983933380413542326938234634936538724556894402466379137502", + RefX: "14308798098313385895541582067441325310938069423308422632356797023544334798861", + RefY: "1035741707898877123076861945405470883618056431156665293974231876270536250398", + }, + { + U: "15836824676781773469036452506677585156571518126562274384238182207906693546350", + RefX: "20868319965163774260283847878423751320754540267982158015550725539594616775549", + RefY: "14775343517037879270320586684222861180609189706605674729870308262121007921392", + }, + { + U: "5347135205819301800298445700431626079051008322542508477745676839324440824371", + RefX: "17136548018042797173013547579534147343115788359456223788806566503067668940369", + RefY: "20714969727864438140069840458219472839101190977129784395938329762197500148087", + }, + { + U: "13911684899210531970362960733485396440327589766797338129378350416810958122693", + RefX: "3708311956979350998223694411243574506013161786504851775269255640284956058670", + RefY: "19570232154279810160589453755323079510802186587331792488823316259457857311075", + }, + { + U: "16789584788250516812387052678264230791705162489279541925182435208535522839355", + RefX: "14707202336800902571182719800149217743898469777100202195434023031101760340914", + RefY: "20662351384566669817368120020015939946274122321802356904063222039981416187469", + }, + { + U: "4880147587798414157895443989514055418797435511220144035512949024072746070925", + RefX: "14836735348433795157709584715972125367755583265571631750985374820051688918842", + RefY: "18797746799941415636085136847493801521146406215781048517208271087754063228953", + }, + { + U: "18622338287017820972633279023079328984355724131009744549969629442187039977064", + RefX: "2614978122828079809200601938008387184822169157883100727572053272328211495484", + RefY: "5728060547708266890266494936325532995960465078297226261143001224911184941394", + }, + { + U: "12939719830830313854836684038004180407675549833971295231992699740121434377107", + RefX: "20714892990802756736864797839011657828078332728300006878796052598388268432310", + RefY: "4296670450740674315850715652677995036928959266028188512445172967713309089147", + }, + { + U: "5813780468802151638443002623683635036851351571780729689136312705163068759123", + RefX: "7210017697076097441034685581290813436025187686032097720402099825734061066055", + RefY: "9984648010014695008929418722064574066118515904219936442927218715918067879883", + }, + { + U: "4364633181281608705743992976264537728967462968394911632763730880462211694879", + RefX: "1109994547084837313440408038765847449497658226852650008042231390482010199048", + RefY: "8577278170430398464541376648607193058415590736486673199165450857451396273241", + }, + { + U: "21721148852016494048990582370530553223211934383966280734750777112138119529251", + RefX: "9122214946598978754999886826074570698371838735602490755957644723779172195325", + RefY: "5652517836441766083677664666916531361547973414185807661768590188612167499521", + }, + { + U: "44237052950817073324933333105341731106707652802737142818245903018259916631", + RefX: "18461436950861703777073444954950696745383764749988860702608258147628825401390", + RefY: "12531628698272525123696596357671649531527046509783874831959645291539896986365", + }, + { + U: "4353754834243887493299906020373932357365586821911976183394192910424633817808", + RefX: "6429614455019804053468835715590968730694486067791465986180437932773930256828", + RefY: "7030902728522972074991599637924404655423845678952302912323778517643592042102", + }, + { + U: "20356779623252988896199112509174517716293727789975619028929140998118193862738", + RefX: "19980681982272412159076673706366094239251565883840365845839902879333772347171", + RefY: "16540316715048211182746832683221249474685914265260925562860228480562609601584", + }, + { + U: "6786030232802039973944347878166205589220078224634649732895701982675941006218", + RefX: "2515265004995552083806209996513447000883973026119148114553564757585293151006", + RefY: "19721111666783588602003742885567513364973718593004323871715324169614035916152", + }, + { + U: "3334862642705948014598966257171139110778197895271752112950367773069467674992", + RefX: "1755158293783097385071825082596301757397153808048027797135278124261385093565", + RefY: "8045361554629734820498526349284820292327264138176405099205380874234256340504", + }, + { + U: "18959298906685915873477730749351714946486912368939936468777826483125359521399", + RefX: "14416679883617128556329254945105192931367502841835811147596046892038929919151", + RefY: "14961501941189380927327929803785722225653774430584193859344638828143338150871", + }, + { + U: "7109147597450154635164962812544088203642632954051968803710331915656298511240", + RefX: "5268821837788284625425162985623780280839863070203228210502636348175513009720", + RefY: "1173399094647347106412293133670958263877751582024493211681140776122259850256", + }, + { + U: "17986849253743767855755138826126009142256899105958731324287710738117952600408", + RefX: "6268665744948486763833009938803816159627073229171653420403379715700544792577", + RefY: "17347232478930579586257410372053219258911032089379914433858124504053566387424", + }, + { + U: "21577257422766552616604053995621496539749934871727481325698951710586692358717", + RefX: "7275459655286826882489447635691049769957679359426623836247822904228032011163", + RefY: "252676520387126646085308076600948453991329759800281328639125115395374311843", + }, + { + U: "4484360450915025763882904951259723610936635716545197825096085527171828846547", + RefX: "8200828244017950733558930110851900276006847993179932168027712143527205371979", + RefY: "14739999002183097574799246771509153315960482469683950896072289469846669006755", + }, + { + U: "3575468898344204418219365674721887388867888890735850542462569052846918470424", + RefX: "21827900115403318080027373513130537083038285806871795293390555921905110610112", + RefY: "10269925923045773526745838346414477379178246509683927038634189568775545192010", + }, + { + U: "779435745587402478572575997382575199902997936939953624179473540122547252406", + RefX: "11762182270291091072920611896545901067510011771989553920287791449354026049106", + RefY: "12292409217498670045968980157000279190847647375089424370146587505190897319154", + }, + { + U: "5762653375998152522274213792576611414652793805131705493704621302431261603580", + RefX: "2870241937046187365991830230565908386279451291503560274602280383693252256344", + RefY: "13906316015556886655844655374164514284868123321543597362503412382453055326304", + }, + { + U: "20081148365331896452921435614858514368724565855817658969391273631384862100298", + RefX: "9464515106529116792369262870998631840508282487867870998523465601714112290536", + RefY: "20187177468383966805689454883780209038185171290105469443624822244996900016460", + }, + { + U: "8744694712365940869752410158172784640159045919981306222555121051603723768129", + RefX: "7745055378702137344729110307033649804647326132788239226535392834831702151925", + RefY: "5108189836030048232522633165117033555063055653613801926911077820150892971913", + }, + { + U: "1802180721151626584534283907306721510363738790955414018326595402005488997692", + RefX: "3177540890436313084253978592858418911974475342251435866796139677983162975997", + RefY: "9650712985837159888953953495280399350184917569085715323580499478495648909370", + }, + { + U: "5498044229795660314357431744928499600512091397329882890620949854419184150685", + RefX: "3020633490265101470035310033849683326386051511270101168262618945512843183370", + RefY: "14693942331102878072237647565437539042587637046724436282653452283640810401187", + }, + { + U: "10084268127535975864780117110505407187436365825126019695178862052734793910016", + RefX: "20782950545138007360736568264947702456706415070481510821651851564548160448505", + RefY: "3662536669096633326145168227509582764642334653946291335319856880128577896168", + }, + { + U: "9654698377942082869505370602538287113388981245907091434569147862499128100077", + RefX: "7505731737739631614459558547090331536199721088115231996125464222133596233508", + RefY: "1274329481939601525372651943269303898735266621788189213912699868371751122111", + }, + { + U: "16569528966013563014821279747163530287350595779373640199158279046052525963172", + RefX: "620555557417074622626026027094620941477921288069346748383991372058764304906", + RefY: "2970096933326310995858275054971413071158633275951664749396576608626996564222", + }, + { + U: "18865682462310305030927271802765039267623644076465792835148281846891508240289", + RefX: "2007091659573694143369494862661952421527141057714678374368071506475984162522", + RefY: "21650680965934648745495382274230638646885235790148774048127271621226097537395", + }, + { + U: "2211415600708949740473354174126483879911356253175014688963795788426029710600", + RefX: "98950708201939078527824573740712518833595856591969051607482410903937328462", + RefY: "18318681047070534740726381226254016555756070559495306191875916948590595875190", + }, + { + U: "2292960357828279965902448013789880985328013948103660567870216290853923369794", + RefX: "1998119352725766708773325564901665489750828315167044289741690019460033160342", + RefY: "14227565127084582826656418214880280890498724762383072439271451194083445903310", + }, + { + U: "16953734160404718183983096463080496617453472634023810835828640222037957761280", + RefX: "12162942186950080329394510829204050006607364376064458337062320243831784028113", + RefY: "19118154615435319252017494082365798800462862682651338879179261861302790758950", + }, + { + U: "5709284504896915583516486077067696799462298808204059045225778161380009780070", + RefX: "7621104185683601457897494515050542977760790896906581817882165982159414693944", + RefY: "8689868628660253543584170942899700656120910407692940471621740631505471285114", + }, + { + U: "5916703497057274484414621377094243693457218667724813504225058730690417113677", + RefX: "7625525107968112463791018106677493589059214104520146006833487418356986661079", + RefY: "5455104458094863851912903803030399345980724305473744272215648041293547664685", + }, + { + U: "3662824221438855078528844024241233543434037251780840534704172462381909700533", + RefX: "8590425467091251678544692314463638991168494663459465388961764738768589383180", + RefY: "10179639552541566070487750537039838514172685544656266229460324522434039079463", + }, + { + U: "17335869951405981445653271722112439137098903706558658342537223740906471054291", + RefX: "2329990361648588521528320120759624277826295436372929564317339737832565735139", + RefY: "10796640651096470686002113335856750055366647976568371821072991433229215056983", + }, + { + U: "8499393049497238575668542533322747434430934810673733777507334012857030813790", + RefX: "16416352963482760538341853103909320708186153393184374354386399614231743285790", + RefY: "9923463747403807387598906510768534534999717619456644601916534172794791919496", + }, + { + U: "19604912741600273043039683429135143704124109426600517276321546016191116974782", + RefX: "3839011948424827671897572136674442745649009090756187149371185381597461076009", + RefY: "7626651628867361731534642594000065626263200713114604212683453694526873209922", + }, + { + U: "12043215263367356857214527306779619943841559743258596407805965936847936609027", + RefX: "1772031827455198502807536877218212058358989353894309416431473131249371600639", + RefY: "5391153228480228155459428147860991312079312771379125518961169463632892753453", + }, + { + U: "2373604101969342798005277086892041203315561129356564695257926995355770136155", + RefX: "8501154296335785279109731673311968548542710220425949820495316369059885369345", + RefY: "20135003018012933868138053880758868698170576222326745073241509799735218129427", + }, + { + U: "12962852926647674108803465161721392442956400577116128380364032074384901493834", + RefX: "12519294359551923657693304015825293376373911717317323661565176629433686936590", + RefY: "13819456646753023754611721116469625405779304695168020174776653366867394372470", + }, + { + U: "15243985546264362750093124328160884525510258181915985146374253260174535037227", + RefX: "12668234383351582907688825440373140594873558600443599782579756639696343062885", + RefY: "14303497593213426467551686434445698197189464243037782398855581674659044954929", + }, + { + U: "17210391863687344084593640242578198837838025822503645028073299651982707015587", + RefX: "7617264955597708896808646310260972567615660249124320970205437745425341006131", + RefY: "16886219302668251588440227175782308810897822514856634721601094676535779505041", + }, + { + U: "15641437193707694094253623993014682695501534816870637041492245989786560773799", + RefX: "17195857865656773561843320717880604405282506373301552950622019006069221007586", + RefY: "3870603936823163617171757996673736708479227421093901969573558596665687315403", + }, + { + U: "8290835429947877258462928078130883963018180124423043414727691545342623903576", + RefX: "12988264542885377120800952049209914269647074097730483441605641890600376674353", + RefY: "11240343729077203285150726935320380317477670250633577980192738083834022511060", + }, + { + U: "11967765582985384297774983504134432290828855146021257789844456593401664533926", + RefX: "3137253108862456911009064561100833949227400641067403893609656067122265021391", + RefY: "6403563577173715086277563067940525148011806680275818134905655880987606465352", + }, + { + U: "4811899967962992486643041953691767135749493182586603683460143726321833415237", + RefX: "12602749750653483501837375437822111743850734553005077404656555811803404607008", + RefY: "5297485128124207251270813889100595316685486224202887365677810386742136040901", + }, + { + U: "12711388515806200550928676207202958626920779571595604856910163995202324498232", + RefX: "17034851204942520625734452987932494463295606284914546358533020838722143051311", + RefY: "20986832517463458708826444556090858337311757512505951403890191090616921527974", + }, + { + U: "7989707557094424297020550699474818235811354990162751287592409209665580038409", + RefX: "7711744572163627991046894380317362523010307470868345998069879255412476716106", + RefY: "17006137190918754734624677764307908608352612776115683348273760344807970629355", + }, + { + U: "908182113375565734496189067341128242689468152931668709975958839395595349999", + RefX: "5788885599920313008896180406669476198892447554364110776587706072283196212631", + RefY: "7563888369920725163065678872168277944486629613021123433228930061784095608799", + }, + { + U: "10495070594230440312780639943861497454036005361230167665180315133033664927205", + RefX: "8120669128966436491757692427177233639913011448212500105234799202582809871772", + RefY: "17616492004519109672001226897112031801993346951074903457075812655762042118417", + }, + { + U: "14677731712014768301810068147363378295313866753094732108532196010968656366570", + RefX: "14413178821900871084966439963881750672885601148765566387601239331739946931278", + RefY: "19670150358198784483617939034604090832096573907896299154016626313254633419854", + }, + { + U: "9512682493101499225168394790787534093735201953316543376217150054341438846698", + RefX: "11829987843465746620616281817760700154762011399051392280662016599476809333596", + RefY: "6154200008211753741388225541325120688709019384087549873677829742949245618754", + }, + { + U: "15958124132873839417296496212320311589247235770016483094293187197247940229510", + RefX: "20630827128334560791560609999580203216161339489371971698283778652236823578712", + RefY: "15114473584671614558876926653234939412408421099388266791227349386408534837186", + }, + { + U: "7075100386300145651554378758797028817618478689170825846973653450373123618555", + RefX: "20021341771050264944044305233876414287224532615419784856367636496639832737383", + RefY: "13650035570680012637564004006485947818574944908695283127063206896290689517319", + }, + { + U: "13620870786307013123813178964833666761729034115758861813592103303876836750143", + RefX: "2048426877941682373474513498686256109893240137774433222257713989333096939961", + RefY: "12529365378415064218837356075599666304998268988291157321045479348131020712051", + }, + { + U: "790066030349554297952363743845049575860716288129347350295656354941309675921", + RefX: "8618324463123172741603735878513822267698120704042010195072369864352633338270", + RefY: "13829390877898019057895087026797841657151999458087770482744875729774396395057", + }, + { + U: "8962468441497911062516276326517744290709788750949373556468803314376457786823", + RefX: "11570968393848117162137286190850825711741486744693551914019425496986522022537", + RefY: "11370560139714436127947974589949078698637239505906845105855313472665998020583", + }, + { + U: "5467073143754896805460537891022954846500167230163082053225346552847829411023", + RefX: "11766677187445475091190960200719488710046708805185217918244024728709643200510", + RefY: "20695776684128878248864665189125462586945176250716464714659339018472719805313", + }, + { + U: "3666328532531497537914114331637079209422175673567775725336300018320077057230", + RefX: "19841144015799328193339094733762670618769922376367025055215908369552041023324", + RefY: "17788692907921132400598954054109950627489733916852060329167241749046594876460", + }, + { + U: "20524282570601950672668756196509443928870767358314517638522540549407663892901", + RefX: "18833066574761881333058281092623495874122911788441047655275982193672683196525", + RefY: "7566388541841169512219615177064101320916332098496915434238358637857515026425", + }, + { + U: "11159610436801065775384534401489562081397381907511652676366041800557836595994", + RefX: "19359472871895430052521358308547517108059293063248358545570078825844341657025", + RefY: "17569436047082240910927379914627757844999945245251013548092390278096539875112", + }, + { + U: "4138517837982805772852879958385448827120367329205079235117068978038943539765", + RefX: "9664445920015519088601333462724673804120441803491070023562065697638258487369", + RefY: "21414975911303340535153249294372592349959117721162650248339112385456540563121", + }, + { + U: "13967337018666611304258991832180491411324884300814548369102794361588725361689", + RefX: "11139703283358630817162469981066382279021731678717407204456475058295737372440", + RefY: "6493465836654664864724684427944354478537477085191782838431657904563131863135", + }, + { + U: "5812410655957578413460971623137916879279947979091665022861067582533425513474", + RefX: "18944321713994024821366242635979927321475394000110465876891601420643234459273", + RefY: "9631637434151836646592530966047305306021793941923759006978621576872349816552", + }, + { + U: "14279467560704589348374513301716374623681814392163254911631115384852910524550", + RefX: "13887962285686100033076857961408495077781366028073112468871708331891727173339", + RefY: "5752055297333023732337758369815766445806897803106899693235475924797644983574", + }, + { + U: "15191301303100629301718696081880567285692902058409756233472874396940679181732", + RefX: "1292571902502130467458485359806337954736086906217447417942840328460827082135", + RefY: "10229742785535883828594876122853382314270813846120600375066394641506922192444", + }, + { + U: "1481871002259299940021113395816698908506974000583041329058765313781415926959", + RefX: "16648452673062895671817686824713808169298802009082840143081447264386519835034", + RefY: "2655650096050674963498662016886095032031377332846252599203999913146168883773", + }, + { + U: "19781684413744639676800145844270468056878877119713454431600512126866299988702", + RefX: "207395257548667419205990417895241974608797032348513671282641995540438505211", + RefY: "13076310966245827330106218617635963408379010878476464718778440801058278906910", + }, + { + U: "13975652240406204540444556319051502696371970533663025346395482631507820848366", + RefX: "6086006553056870021811073384376334888120175926006389883939153345021104722646", + RefY: "17042344955569852956566750766693257377533154512961498415797626280139854331666", + }, + { + U: "2150576103725978313146705311192007509864284715697709410936108634934871946430", + RefX: "11675653376839642003259928828497776448213105327439038670537706326090390937874", + RefY: "21263271799277969487905418560332188755977928136905297906423744034615888702776", + }, + { + U: "15806769798494457335566003064901507025823867734021625933888906591077788914478", + RefX: "21612451098602428403392571872704495013825434227963157480372885235780184933244", + RefY: "13544128954289216808770220293822515330502483121969645883243619175733140944918", + }, + { + U: "15150131175218340615789895304914258757044298662663513277848017154446753423357", + RefX: "3196198659681115724865965218892482561683076647051502180340916868915249771557", + RefY: "20058223821402739494929345187153478998674729076110169345768724109000209190985", + }, + { + U: "14770497576224681068887274481348430978055371171496339978507754829449712471311", + RefX: "9010284536663280233128859533088279217336554747374681339853339154403693079409", + RefY: "7057526529934012726141897635231125393989715491683936963316436818735495070313", + }, + { + U: "9668126308782491028851401736526878298639064603063397749089566621854678656789", + RefX: "11938921928542883969101887118643870444432470231203604564644221734225952597171", + RefY: "11280477769646707263648483592869134689588507970732451847753389360645764110179", + }, + { + U: "15323866956913689303849035930378774897112614985453730365848069926085659776519", + RefX: "6059885235685614235116507310678826163981379833373640883087800932735940444109", + RefY: "1157827861503955554216471186183873597618207064370494247193881549663226222601", + }, + { + U: "10003387898018811455688425887421516072854984619721870382668592179190950810583", + RefX: "17527684498213998818053099047968939161499768211185540331953958079836979843423", + RefY: "18164473635649247855191255735446789466146762355761804650536978291384326878023", + }, + { + U: "14842196263306240626711041289873223732939037482524444124708262680646662326053", + RefX: "14332870890430551663653974208329912097661561491993261621504453432669334165169", + RefY: "7297137934597300700554997663280816918130836268747751963903824616380220515833", + }, + { + U: "11641574930086805607661480640147157045082037022635166986376751799323958045262", + RefX: "11715673247595857748032817639250453709882376824011100475891362809889555810785", + RefY: "6686491553856762734430057821063465746886219308847142167149892799698809642668", + }, + { + U: "7342499988040658860418817959613928168634708613491040992589195223928024749385", + RefX: "5917865953984803996932877599852948856105860326934190996719202705583465335872", + RefY: "3056981740483408428811473174131853934273357433734098159440913648988524140261", + }, + { + U: "8362345093527406390733255204591622676396354967970328330297558243828532032398", + RefX: "21514727770963242188825950560237866554637323201165076901189047675249295918774", + RefY: "16863454975173863315259875965975756449252585570272607119369880722362819318958", + }, + { + U: "13851237740258139685207092423001517661428222888456044004032140769440948961855", + RefX: "15298071180589670849181334173375667739058798453071703543458896860990785650963", + RefY: "15441845531527046685130693712149810030122688598955010707866694806713447340509", + }, + { + U: "4535366182259661346945151790195682436864588544023607153833067125433560882125", + RefX: "12357378030238001394360190861063272058126756351812340246129804538113153764097", + RefY: "16831470845662634900897487016300135295979033013291165444414038889885055441749", + }, + { + U: "18659746427954086319223668370512045815184899222334400304679451613257651571873", + RefX: "9552276602804128583835280898955139362912092853455868046101782761817672545967", + RefY: "5273977746757175516644503583079569159164274027954017412968683769391554652211", + }, + { + U: "2277584040762057222706584350552670180648923199593400597974330143810633695360", + RefX: "4766955791423738822150120531749326722220817093015319984218701147234599349278", + RefY: "9305970063056781347772799469585450172807761391430639365493965284682264596698", + }, + { + U: "13243524346962507476146450000860478647373096623065800864166812729615544496020", + RefX: "13803623603818149966240291689187353374861442018283465858399458758132346150164", + RefY: "16938808062407584278214295090085862764701123814841583299805191890927057999530", + }, + { + U: "19702915149256070437839704997114097822328679311402653721971606461564147843282", + RefX: "18815041344661975379948813903747492505653691821036944048399954289381847578691", + RefY: "7661941049734599827671113150017035995146881728088903650311143711279130220276", + }, + { + U: "15158835983648339373800327717037160349393114270661913531576589130604794332464", + RefX: "6538903423506674443777139278127917525568392436172602040489211351153468284675", + RefY: "14401206064697457346398899927097999640744699722592830542723749246316045382166", + }, + { + U: "11810650501750297099949491629335700823874830062739910424089970630691097528016", + RefX: "11567120710645150659464894445631877319650877786039316344688027435408236589265", + RefY: "3729650038752050861336730935076631461575616094979568368570676807547338967262", + }, + { + U: "3460814045461771464127134707850079595105108234760166883469624625630699601635", + RefX: "6330382016659647546456725063536752720054798444915602325839007933005103929207", + RefY: "8468830435515840881968331353887874330511150348268542050039026089259735277955", + }, + { + U: "6157546259777868448226608383298753180511039801159588264035342472569274331994", + RefX: "11947732279245366601609953864148124651583932130867273271727157746635557287965", + RefY: "12534732876959483564570732170032957963234262227803130255680308916294398353458", + }, + { + U: "13655032581046567384234184763524649410259138796645532817576737613503967648483", + RefX: "8685043996968813875727419717749751137547453284761302303240264149417561798424", + RefY: "7724937132444298889288489015684116281209390889244391935349956203376843011427", + }, + { + U: "11108918575887700812190998984992532353493763912417786234729560064175349096661", + RefX: "912772220679532544494867837294820440110396538925440577011317361717019327803", + RefY: "7682032882786608044710420195645895038444868844345233382624880272227532268639", + }, + { + U: "17870249217182246107856721108260085777241215799648212209143562539141068094052", + RefX: "12937825438248422056791956738327820938700367172838567247205340330824592292819", + RefY: "2499243785157960779653933429309185608579945066939279588240224117226910005018", + }, + { + U: "4418405328424290954632812067497981203278510258886521072009854699881420354347", + RefX: "14607229966429732957039300500794661794010690549133000229862007032726284219659", + RefY: "774648169952593699113474058035171013879492210827379914998157671992439073743", + }, + { + U: "5984443786352620474732583116159743362044931804349344672716576135834395121450", + RefX: "20867462160582259691532031379073057760075612425513746840012976747217964756150", + RefY: "16296128717574368863617978643934701321770302703781838702363375749909253648686", + }, + { + U: "5690134124544468045094084257520316408201080018599693893102805889562656967741", + RefX: "16492485716130932954954453226020285804343111391394633666010314833585776449367", + RefY: "11672964099315576744967074127321113453364407394437773403659217150233446523825", + }, + { + U: "3108819371515732341192289244135496137679154024983076617648265727011477792484", + RefX: "20309591265948452278371177258507046830090255309392030138214510746670490845974", + RefY: "14062106285860089634160252482621015190431786657317420462042936321984405303902", + }, + { + U: "11417964839273744011511472102744155983703628367398479455110013278127586071175", + RefX: "18011296267597163841377286944338783001477528591046243944974515703854931514608", + RefY: "13961887507850285629724806027290003292584189911721269933825074067496052613703", + }, + { + U: "21006575575546094164983419790611140680169313459074426827987179562815607591545", + RefX: "1786203318540104250770866489881824474266834087215576937195986893147929339238", + RefY: "2508613179981038600766588287837269106877346084842485344120398937910849089761", + }, + { + U: "16369062645046533796216071127013433526471738395401474348665961077980805551150", + RefX: "19712244935579749062941753970317107163060424097269563410675748628211389286946", + RefY: "8901801037945293753342017485929790157237174901679784750702576636309620742356", + }, + { + U: "12210076816275045304791114743865157589328173082927390721189856728548272256631", + RefX: "5717131288785917567106319683089139781837613327833824449427543175804668388836", + RefY: "9961853678643902213445655963042987172735530043741935214693873529509163109991", + }, + { + U: "3511184991136011077676911917400937812110332701838231846811921413401423513941", + RefX: "18035197258875039360693830276862841789930162046619401005741202118647843927840", + RefY: "8237974922134819967576627230195203002325982032309879088259548597766136311683", + }, + { + U: "5735950710543017677964954865997411731621644908668984472563830201738111690749", + RefX: "9121393214331017019310863968524632473092384788052863061257903260626394217820", + RefY: "4905109838415533257941335737529756103640381902603204824326302850262649621725", + }, + { + U: "4503322824491170726803288990317598065627007996285343048138749297737558347289", + RefX: "9587627608886557333504693570394480581106109028752947329872580756364051115989", + RefY: "12215427882748339021494828897503517848928656968072438296131662448966881633149", + }, + { + U: "13437819414469302847769829161985408364941758284929631564466373052166242958423", + RefX: "17813853355097559896449813951227773068127049125346072139286967225201254711253", + RefY: "1493866241199662898263187981651157567734064080878701786904422722028702157981", + }, + { + U: "14898542793203935477897305980075712159745612258493009736108128594235099890295", + RefX: "3944620058769996363348745794375155392381066513207118922549832376144940862949", + RefY: "9667610025661510639558459183836228139438972736287938157222990077271406556957", + }, + { + U: "15742377134007879329138769844844430432856176139153029396245034258330447252078", + RefX: "18585844684639262182137880621461671648598148980064825357476964258035369215697", + RefY: "13755634857016059301514958785250758693022781424854989126029430376336000853006", + }, + { + U: "10411924508543150221123288518364706605958027183884619260955373884452463796822", + RefX: "18833604122740323081266300661235082577683497677422259678448014386091493596873", + RefY: "3314733493752142109808049718368933117783483556143297290845574321941344538380", + }, + { + U: "8771124266970868260680074884913520874276618353071484443953702503588920088680", + RefX: "9012912504605274963894267732300936113829218500851346108772727248401789847275", + RefY: "17387916075554084892629462641651411568237112572438669521719597989844792675100", + }, + { + U: "162169602976711772857950731870966024466066012210432675417549280616837688479", + RefX: "2282014266911958429206286314471960224436857079373688180487515078378843424850", + RefY: "11690119967957297333926768037037481885099788128016589632399944219529980179391", + }, + { + U: "19843027620019729413226351478184178462778970030812068545224180257154964510454", + RefX: "19872028330803848150460647924714873775323187808018794447683814688205104370771", + RefY: "21308026380597821462746915316312185486517062424621830947617803224062113514868", + }, + { + U: "13049590106193234073303478917697684875644271199140026620870121635932423817381", + RefX: "4972878709112529720408445290985146595750700253938539473723169758563399051097", + RefY: "17187715405148176168297883889252835730709110962663429328931698597945279128431", + }, + { + U: "20699655434029756934587421848812423283824525588444386687099577964627844175235", + RefX: "9498558691951543320637253065638223016187672430684173480963571304777609907327", + RefY: "2625311574306461303642012340218285483964733162722238346947334634352962824929", + }, + { + U: "21457043369593928978273141344051285576294040127299671134888885567584566102495", + RefX: "20454311100069809380518257728877184970692442135230739188811340751451161580553", + RefY: "1708272261774999742951739693065053394782849278959625285660048972832096002717", + }, + { + U: "11593490582281996356476053500307128304751338620304317721170476466061005308226", + RefX: "1973975540033068279992633435378612568751333864984317801870878910239546445027", + RefY: "5969035537863874370983047168748058176860492183875583176089457378104689433056", + }, + { + U: "18780674376802847449588116491000091036157701175929181456044008140040394589986", + RefX: "4182215250279513558929902755157856979420068019540664299731245589827890173094", + RefY: "5576302159315520015374418538706340439821696748672782774747710788726922723344", + }, + { + U: "636086663399899605258198447991582800738178956540284906019030296545530860751", + RefX: "15350825205478653582824209172273050779314140990151823432884966012989136072997", + RefY: "12320381630151843636169104541190731332923782098506486084620789137129527382929", + }, + { + U: "15109780033089942764323759849330501524892031284536104453509252969124877980656", + RefX: "7374279732746231737027272428033961658274186129846651744153568810643223159652", + RefY: "20824209624269588626907655602919140700602383120892312037151148840365555339448", + }, + { + U: "7037614575032323086397512378668053184852437148350476508749944080165470899145", + RefX: "20776797601677307723910083870594228202621155548073033140529760779578015617665", + RefY: "9652333468451613699510123112098508419195313535956148944772396816943883131127", + }, + { + U: "1944958004841895976356648969313493440298753839278317913697506032783365016895", + RefX: "2481668811181967747916172576634860154402746534307640696880211074749178504274", + RefY: "7580496312326096902618094939560949089809412539157178214791262401574890276523", + }, + { + U: "14710127105109686250313065540672398342198147023339564927637890647308427864756", + RefX: "5977863540891297651137398005174098676354873134080395264106436178468344745103", + RefY: "16007040877565602326585828405726232904519716835042121095231795613305185076686", + }, + { + U: "1079360987781370726717219731622167546306627435504431064744977218454792184995", + RefX: "15783536833280824394300964371051507666565601586927308956017682852271222320481", + RefY: "15663199255548184057465811972834870316708312021790076611782649577616683301047", + }, + { + U: "11777058133816152390497735164393028447166766985724628980325406375800252993231", + RefX: "17789639835129668782541548772338001428596272892444469971307652125095746975241", + RefY: "2133029442800977190265144498363726387070541088316629937046411399611406264415", + }, + { + U: "17286794372133011605231492883012148447790912258947912812832788334472197535339", + RefX: "6708583543487195863799534263610333931847049414727703627086909758971400654525", + RefY: "13408098075843937377444818266875260222376110175419630389735908321790206242321", + }, + { + U: "2730802541817234568651126113396912194732170761281715883210702188598170162105", + RefX: "1005324179568032552682992430776822278888652532388258189906792364901497159579", + RefY: "5328414624540322242557243007791445455137368912938851477361448899453304789455", + }, + { + U: "6979626383735174091387946151612919346100434150715403984950472774595059117068", + RefX: "9079093500866192867180749013876642004817005586166838450106477490534906417948", + RefY: "7051406020897528247564373156469515189047132552630296838255954475328396916990", + }, + { + U: "11169525697702081976014846108028942595831195804820339367485014916003665860789", + RefX: "7244875853833554713548914623928119740455316025369573809321768573237501521456", + RefY: "21006447891521841078024283464520554573530491061108629419509600006542837205897", + }, + { + U: "18056769597692625186321413507211214568888494313026133179197806072831800869858", + RefX: "588213877550900473342963735267770265715828141237706508393346563451127130022", + RefY: "8405139446945527899144310526905675801541686056553323747514822691938692787478", + }, + { + U: "13225828227905554179047930915008359424489815492157120993411081937229318776325", + RefX: "20725570519316698037818071957758850214952124269313831151491129316050056140423", + RefY: "10212708774214666608066988143119572326966645509283464646359084733259985074107", + }, + { + U: "12438180029469579255661786423842524774321063727754797409133750478636361306942", + RefX: "21255531224420744775533873128710818480419462739066379047331830416173945481800", + RefY: "2925215812871827501680861842650069945457094332850632742913995890699833904878", + }, + { + U: "15791630185647703625844349924139223577818808223096262047319017352501540227903", + RefX: "16166077961791845527129201286543994608400361308854177189809224108581878684714", + RefY: "14540574568472987823681281920022082785087608280773148701515302938791469784867", + }, + { + U: "5658955595804811793741029707121315131896838945746148088628590515661941418678", + RefX: "7425333152508525240909048854058926805577553015379876001023202450480738532407", + RefY: "21844023180889496018171981512097296805900217361073750846689412195764951576934", + }, + { + U: "1093628261288007853192178463479866424046552006445683224420725027213154042061", + RefX: "2740334297669837396053638106275903883233970861292796019177520414691167587625", + RefY: "19723229260722377649923229762566572479554521638469751093627050697775559496539", + }, + { + U: "17740425850044240601884228581706659902197779819729288189236530237262556837639", + RefX: "5996077628810229938928912185779719265303165893580920660809928356118955908834", + RefY: "8315599433516861734951911275907256194336742193991596538089999266270179235767", + }, + { + U: "6116745734893633384948671368747544589028088956524664020807692472881914863135", + RefX: "18118323965123228063138598823038385003145031821712373370430241980244798224249", + RefY: "11502932941828696440153313267886538453956204294609957899034357739475037146291", + }, + { + U: "19344947923099479626871844537557701111253107413023481520906875067504209496198", + RefX: "3415050271578533199764366050967662818554033217658936044067870218295262290757", + RefY: "2447758082982554166805532168096087517152843373661479216755954347021398117536", + }, + { + U: "12211044322977390767486408266452866773719958088792810977403482341586535894836", + RefX: "1347942584634728297635012063066319097031600286014483751930752604927668326742", + RefY: "6785016741672098451893678198571098835659300680769820914442178265899697661920", + }, + { + U: "21722391467933412753188380572857640364649052565707937630402756503468394353586", + RefX: "3415370048311508471535672132030605838850719021777506545872261021540488758479", + RefY: "533715660435218844470671908781054213509013808522022514590102911384503195666", + }, + { + U: "6726851912262907962903254302608461312384679217921595842294436302798322718691", + RefX: "2688494025134451604037857944608807018167307753390145054496516894470873883366", + RefY: "10533333119851915415907513881743210968820880944002699163831848434332363665861", + }, + { + U: "2157706254903395842894500875183425147736911162591977392064725564862082809235", + RefX: "10783166077944408006452987800243307469373647377659881902504284248280357661943", + RefY: "3088875156150734601476346373010714630683723937491922427113192796763830651853", + }, + { + U: "10758734267168429367290472502846874967281919032177034339004664110321165231996", + RefX: "8978751886876855779480210200969810063434214410099048911304705463216400047563", + RefY: "10743770464253466913332540386560172927593388508689728112670666187812181429298", + }, + { + U: "16762827025820352154946656489027660024416654294876393275906615709289967900229", + RefX: "6122643729670386708918757573102079160184316884160689527755326309929665813442", + RefY: "15573282942601011740370724849689402887435447440315036878288817290507831103307", + }, + { + U: "12540558325629778304897742126517642313382611178483437919365612676116140360767", + RefX: "3412777180084704089571512785268663366728795923532253069768665262270206008896", + RefY: "3132534146450097204328915095415885506681889179296603987818321721582931099079", + }, + { + U: "7524858399219784792363008083174054644924850208630098585524925068630140962261", + RefX: "11442743450062447490047803617058238334245454968224036161281171431081179559011", + RefY: "6964216346522868635029080502499541858931441334031780258084679824694831710667", + }, + { + U: "13170089731198698075555361268266188609152755379715295819831349348815012280696", + RefX: "10759645938243612553149190337230011468882087594072662769222927879425898609708", + RefY: "20826175661397680195959861385357505744602955530727027242027296860761058513176", + }, + { + U: "1920722457256667109431989555180247135127405226984291381857799458115105567880", + RefX: "1897001135233894596488871352661263249390442772446913196418973295624411323933", + RefY: "12931104141097811403452391745065507497973799725311307651443962042655883159818", + }, + { + U: "2570827536079244073089852468689615614444919689340940717457096225720031211571", + RefX: "7997485878791611036224218706651253701310594908954947074758580956745416002191", + RefY: "493319562074136101241045904506967418812966675437533688797480757983700523469", + }, + { + U: "2965379805032775061829068175808925533314161345935738639327192504119834446802", + RefX: "15258033714612468228312173738856078327815952002648535237923081123643773704642", + RefY: "10128819476568519045899117357279969741658063386378665872989272499045129044630", + }, + { + U: "14907277350663120038946426562987235577304665624706131523846307776659790509817", + RefX: "2098575632276558977112791034270657835566962339540615473306516537274965666080", + RefY: "14866607835228585290742280506386710153851087094547960339050727075359876080589", + }, + { + U: "412461633152673578816151607417266224557116539015877535050708574765214313809", + RefX: "14551039651449226311502509983827062180585369208861530467131605633729027664122", + RefY: "13912329333070135449502594608073476783305416214809630333943813320427351214349", + }, + { + U: "14363756956441504648818578805511497108769248067149639302002608892763792280006", + RefX: "17000103632751618683989703545739232576101467077922264569816427271942157031023", + RefY: "8880664825933236031055796132411113315100437619046715182542525597106733492884", + }, + { + U: "3354994234094730284168183134049802014529220933485072216447650988805311619404", + RefX: "19246513977741526534417760179245486102181183538690312156092640086524753116852", + RefY: "20855804322587153315966093955895038088062928259530355145189892609953095631712", + }, + { + U: "19924403501639894959199628430349985835734333827773925234334069993398556836559", + RefX: "5490684206737050944800056908236970673394497412072530170683812054225841322446", + RefY: "6494391442007629957281558631015861528980830328244555492617935902871647813141", + }, + { + U: "17402555773835980388962909179350704498037337381473179543675435314326471495899", + RefX: "6455738877373956334985279178746736316945001395629722716721844268105763372501", + RefY: "9509382626116464038719403589094142421747894760878182795373651722359610622381", + }, + { + U: "2137934730330291446003797173624629839277798176229881089419532969126057838408", + RefX: "20957284079297003583553295324139741925048185202613313609241971201426677692832", + RefY: "21130182232415057092300625871038427230890055512709199219654991985199051638362", + }, + { + U: "15414289359269779641035248111656718053118110364881546180553761795971365186824", + RefX: "6902315905430253984078863098644801908344054704886158053054324485381379056966", + RefY: "7338196187519176500556432191027778832267110352757231085730899532965008596914", + }, + { + U: "5859706896197148639565452106911009024318567235562700480803915998705053456869", + RefX: "14806388025351292481615665694807725344327778689823480220697663495788949460133", + RefY: "17316153009233768675569504269605299803702832630667038744247660268327858418293", + }, + { + U: "8554244320627995788683584274052037062784843246477615188115285878569509879924", + RefX: "1387406004662282027450659778961718003786333196190356195774483999882363414961", + RefY: "16637167648103605108779224236776119862743973455131531344212527926386050080056", + }, + { + U: "20257163166539821735597763178234792939334592490765237814198397907441355142356", + RefX: "16313829988579841271182404563330205596644189898742164839882350125953649999436", + RefY: "261752616808518489698011432041637007916843474748718221407784660414692889358", + }, + { + U: "1856164522839487376702097089342710164016214789751985560930573972675150697729", + RefX: "3990446288535628543793727523574357257110009222156670009210719219642608434873", + RefY: "469663779176036321911155368426998638793533707002845197436394017752101085799", + }, + { + U: "2718264969792660912518101024353044590283935331618424877152472590440874777583", + RefX: "6886769284485852971320819745205884986248512516674948453235269509292149994763", + RefY: "12968091388949502548498770649119547491517806977233314680513167716320143100661", + }, + { + U: "14928832040978038755148922429759049163587255757546488084230268832565559613307", + RefX: "7702391488428360794023578349508502620351088888394579524131109926728347333931", + RefY: "21823403314917311554326991493277073318087478830432923824972765012994821724077", + }, + { + U: "8875762742928572478228934172398646150664010290361230023252380943760986082296", + RefX: "21871717783979893988922765293758845139077902147497670228628725017538080971473", + RefY: "9751925713098942884197257067315024076565190946401117118614836670001450562268", + }, + { + U: "52589505951246504300569430009013266191983625550359190618300445515803546117", + RefX: "15850439687087835433168035322718584705894985629950477170203516222241626601562", + RefY: "12700167635258546218464534258529344309160975799258070977356710122092208991067", + }, + { + U: "7059826882008179676409755817426665747764847296719331812541637601205277198194", + RefX: "10071078176298471906833054645378886133657781319250569494361528374106727280633", + RefY: "18300192292678308516381425601392959036276939360031170419443040326559281414538", + }, + { + U: "11424275370043399984071752308888908222287360620577414355594173629008464486691", + RefX: "3458447903041899234012949274434784480385495460058876660645286811332592085780", + RefY: "4849989746335493131309362239575556465962068336334176802255550035858228673997", + }, + { + U: "2553424824786328638383776403696851616161985229026792740037000773982261449126", + RefX: "17494984686879984003798354671466537529211243947163629364331329110672454757783", + RefY: "11150990946064036796880532340849287880835769469889662874838507765021076482938", + }, + { + U: "7178896306047281902023681925077776991030706412218401123731674381342383019166", + RefX: "19657785381807023489083682759948904948147783162742590692208336837531441009094", + RefY: "13039404075431284559044969094514507026202276895356160808571510052944814882194", + }, + { + U: "1118673381783304682693598766330298758991158382782452733790594762332263657946", + RefX: "1072223045806160849142527475821125993032557115618288997700814342041604072042", + RefY: "15044189211693081725625115593833955958423101966298432155638338765608575852652", + }, + { + U: "16520475021647383504532661268265597931321672736376228042022928585937763308127", + RefX: "1299277724807008599257774988004292726904783341075059784343169474153612860451", + RefY: "3298030055255058745861807835586656028501816738123937541480106178344639207053", + }, + { + U: "5160179595997117011555483176498272203228005960149938690774729392713915662080", + RefX: "7568658469040036481620401093693260479597237296464944742286950935188876244259", + RefY: "7035176405354104139370670478587252083600753184892331175515422986721028294048", + }, + { + U: "2533089900934961045183240105756178357602530435883932858187700346853821181647", + RefX: "12607189280535544232848419031455649953609059995614555961454819414957657294986", + RefY: "15650381908612920013984125068714742262197436862495518252382593438586991612741", + }, + { + U: "11712022524767327570068802948454201726030282944615830583377313871770862046206", + RefX: "14181935094585875457686104978483384648256737611102724771574572999763864764111", + RefY: "20241197931275540982287715444721643308576645122242025088144371001743056534536", + }, + { + U: "727078990696537843103495688603619061534509687101232251757877992189289146390", + RefX: "235243332699968789797898572242457015352962890705915616635834678074638060189", + RefY: "6591365062688935169143592814659486582644040516864523418593690892693871502136", + }, + { + U: "5263489670143413903040499643857142908050685806565119540894180114914436207471", + RefX: "11391383846282580435975417826986972877053270432493013861347374144313909509780", + RefY: "7571376942270199926774670906017481066453824541392195387394867568138389658555", + }, + { + U: "20311652466308862681653589964443036343916480346234878775343176016097394592564", + RefX: "19738355141498313792082128045496998251395008883062628669882894702137488548296", + RefY: "13520818720070282508085534864747781688796775790727729329235723558556257437292", + }, + { + U: "5542215851308286940705470039734633427376499753414068670145114832255321433858", + RefX: "13975535988678335983963532611128857166190226875590261829047604024497572781664", + RefY: "11954912772260916753350862600477223425545474072251339303148193044313187762546", + }, + { + U: "3070235493599193920231220226269100281839235951911435535588976972089192786680", + RefX: "21410223027542923983806811768627319179297498018983925989527157273185473761521", + RefY: "8817233359786295549934340097135236996066526084099119620636669559109542315188", + }, + { + U: "9656610370576052221495153111180922997318996087755921837373874972812592702526", + RefX: "2425564298041439963633829691680038425925741609419080935641275210968296454452", + RefY: "21109395517931973641406491200244542456152361575800050921444815249428416637208", + }, + { + U: "18951429723553880009665240975039152419781240832652651145592243523266931308811", + RefX: "16680145437429436271231593828384427491791116804499897578275769861830571301155", + RefY: "11831283547533872017365552567470995853657373301808852306057309653835811333767", + }, + { + U: "3516103246325894377991260391450493330332750557926121076342552267075690037470", + RefX: "9027554074283136060357462481748310256487394910388786051491857003851951594453", + RefY: "9402024107796224153553710514425698728903613132729561765580708071958204538210", + }, + { + U: "20989473228966351100611056009182530976969527412311209626135343839101020370732", + RefX: "10542171038084596705825334798388299865000211618123463682275156955485295514567", + RefY: "10771174905421642172808791639699666968173870677443236129287737646573290945670", + }, + { + U: "14948994430405768826595883765490054549571784524944916050343980049604709408782", + RefX: "7190485041740607399535603775973732737525413708471658583944849441077682107593", + RefY: "13243220251690391461643214296758549945698870069400046827432065175106465171410", + }, + { + U: "18366511597366028167861001678733664318611529137083916115912436107303647446903", + RefX: "729842178454190338704431714410034401848261010147259928547758657166164955584", + RefY: "8271505362852443069193902829822287373550625013624823294534793355982532135499", + }, + { + U: "17133488328066032454576025022025962225730475384425483439331249559755185283546", + RefX: "20939608889996786702610794906508674846969880412361013469879655473893913074505", + RefY: "407006963509586690639708615070797510334516194706687148728461123703700602822", + }, + { + U: "8473767067987676247189111718421042823523805314911573408553050484732015236785", + RefX: "10206080253701598721143397170519367619752056572823685734759773088447026761534", + RefY: "3012222755060153678778288170584198609625769639344137197949238686401056821579", + }, + { + U: "764685088905358652653924370590753365932627483526387397864217869754179733978", + RefX: "11295992807733783158940369866695377753887598973291452964982702185185308967611", + RefY: "15730930534272647684113868772480934420216302570933222357679222380131661317046", + }, + { + U: "8779634225494750009118492468635653313756481956740393053879889773157633478210", + RefX: "13713105185159030102217445649155010868450123123159634310426472496630960054337", + RefY: "8317848068272504659758156072204581473880598326652406352536159441751378549856", + }, + { + U: "2792422261799355266883973665927129695846075319697612988890056899457230586902", + RefX: "19320400995869818305323102744583429305723776684992700160592140630379667828145", + RefY: "1316471352126047008304655368361458884765720620941848124176356411337898473524", + }, + { + U: "20180118418181173017528925796904789152494827435192256873930753863496386404292", + RefX: "7044444084559336025504887454261631936644216115232774913368932016757168389956", + RefY: "21442378040063868932465258623009930360189549554015983093759667246334182801216", + }, + { + U: "16899551729153600611663743396331720845550503064632223107906298971800812154636", + RefX: "3340788487983562166942591577418154657789323852436212379654532814153050528433", + RefY: "3353032600694990874551501735916936781034674694497843281194138188201137143786", + }, + { + U: "10331531333336110303446648180717376469626035233331306695275449577966648978563", + RefX: "14791336576063434788031569566805100236799206413302725345161513105535017625710", + RefY: "1225002966722332236390804229967438679036519408554661316032543703412610834819", + }, + { + U: "13316015901173741991974209231361045068342587352850191404820992308536618346015", + RefX: "9669874879419563681749464064471619225975517543886710058339081172181259264436", + RefY: "17010020416615385042235488756036138977302260401034433926978297025142777562537", + }, + { + U: "9463554016069504109494016083365274937530089969475321019902582370871595732589", + RefX: "9593159039624262562694546105611433218989709043420353591829546621628810061242", + RefY: "11087828335477639357785192027438812894072149972319895770168711200270331736281", + }, + { + U: "935463840089041536736099248022210496782232663605758659949977757927296172649", + RefX: "8348277324745495700559188697402486130928377732389436551477615241975199721195", + RefY: "3244621250137096405672107359045346416902249782001226665995210053993173799657", + }, + { + U: "2694855452543693468612184018446740657264903877802661728511018453394704050996", + RefX: "7354768095472772115397091976597762127012566957463306358351777012027862347924", + RefY: "11965385933990700453484689063267666263437955516824359439566654483954269901754", + }, + { + U: "6044437576723679995142997275135277289381920366219817405223112486899846821312", + RefX: "10155832310436790557116336681237221827374537957815739902028765014483222251284", + RefY: "17186412334832875709752946172430199756905741623570450559051906984390465396710", + }, + { + U: "2481095117182354497694325851396013122573519057664055763906417846426978220583", + RefX: "5592872937796999819768050181720660008549264951400063263416771978652166247055", + RefY: "12285920670885702565323959743242758338062640167025529244846232078422581942715", + }, + { + U: "21468153295303145790958029264054730313411405729170361950507963407413821109008", + RefX: "4599954969200942950345546447293590632750436069145240951919171704230062627375", + RefY: "7509524878138628427278095943385157030486102497160997790844847075400713891334", + }, + { + U: "15531543637002871474423512755499708184349115746644242716990916831531690991732", + RefX: "12753626373259515139272859849542757862670341001250501205641107226244562705791", + RefY: "10938274135892364873780659093335381790541140490613927097502137905487265363578", + }, + { + U: "403430821266157797559570256628963955262564507166811064757023350010357057166", + RefX: "18340875215225502040223758861866578142098067115979607892384369459055283618717", + RefY: "3053833538355322238137967698549863095488750841654217947727942051257856482730", + }, + { + U: "2003714798392323620496989328732740325680026161309502836814040945053189531854", + RefX: "21778658796846525221538627265822789378302107894273140555139826280795695861238", + RefY: "4365329699519944166555866909917909222592064021970118016175302379148946382008", + }, + { + U: "21721924568856816405536201998964300018258724379767064915913181282747785082788", + RefX: "18313572385407675633175896690927720041715302110613283775034331954233395351336", + RefY: "15505490446558719102079009654671422590160049882535816010464072352802001574138", + }, + { + U: "10800020338685831357911325294730456713324147214619152692403016440318723219041", + RefX: "983628544210133487771678279290792065791244184676566390965694014793056000950", + RefY: "12134787326065986704162920089284207088039587015405253152289150661858176708387", + }, + { + U: "5144994606319887678908684801645744746627888043472159628221901989440288918964", + RefX: "8844045815327521259453926370109063603875310696727497725564982259012487185828", + RefY: "8896933649975970879107420898286676179149345505639977018135984268337321647202", + }, + { + U: "13537349874347271613307879514072336573235064678350339657895072000392463897644", + RefX: "5162300042007884648285553675870339227644846967425600066357872088532199612893", + RefY: "53342973689215604324063431900176520599445077416614565281593293761365892838", + }, + { + U: "21211008365667850163869656373043181241522649812104670459742546733324752671763", + RefX: "15493407826066583171109177811064386814430724776357291423650023977862152326852", + RefY: "9655261667572164925510660807435495303483010987853384749754119655655840571941", + }, + { + U: "1037273398066117781652303968385975114334908743758725267987395305762971122711", + RefX: "5555127564382386631970892469217545326543245437757328845929399694645601304364", + RefY: "5508491886089693409387853940910847258533771328653952520696585339098097562111", + }, + { + U: "15115824820513100648201092992523119006523038191098110942494956367552787286519", + RefX: "13584446690205275602793854294619105896623983135124366506008790900859904186137", + RefY: "16741205245379381579401393583609266291730780033147290813957291494614588946839", + }, + { + U: "21030743958270153908584559406698891691255223605243538225186565864431898266065", + RefX: "11614690227522096647275307085542746882924908621067526010906467173776252423039", + RefY: "9858503483130924360701484931274177991158119583897000212925609441004159141075", + }, + { + U: "21160457431325631492462686972122796227960869784994114790129092880067027987302", + RefX: "7165450719587080246313793806078842201927475681384904766003606110921217488910", + RefY: "20803164281184893539875849990372575259306638536712211798269259315851231935596", + }, + { + U: "2667176322707437581296567444302651524024542456044490461320187721753541673411", + RefX: "5980654534879563298168725540525016466551261887510549893034342277670562303243", + RefY: "19581125770636554617119077171943994056565494740240182961187115850053305873675", + }, + { + U: "14437478774142975236520271366594571203731969569146502066838410397695257708877", + RefX: "18095732089454791567583960559448312696828409051809138940711278778869933981737", + RefY: "20327179283505195201359248292069538033835566947005924931782581722477346809149", + }, + { + U: "12898164544547148193142079702808547094505270802963848101378874104104058503583", + RefX: "4077860631932363481238096972675356055770419789895603025775943152406073683828", + RefY: "9290992851304337290498409744591569747732275176680598682078015246873683127925", + }, + { + U: "12263994523915694526511580269482585507413651602630702281818211216397890473311", + RefX: "15978558238718503726147176052807752716755066320935266280663470580912127047824", + RefY: "21464745151128871581986964781976239566979142499678024065715270116020486850693", + }, + { + U: "13574780890582387782262219654396062448142775174065650370545358841930997741929", + RefX: "16810904890366832964903495125927028446235627225684127618018291023904202548175", + RefY: "5946050511009049544761161486467077537081772901016622669279304341956755074271", + }, + { + U: "12793821333915244919833963425752933832711332871346804951706149393183913927163", + RefX: "10601329972334040285230252597050618473985460442273127045417105379048125704262", + RefY: "4577747128789879217437793320014735810850873567116540777237850153614598158093", + }, + { + U: "2587796529826676876219211884705995020384246407119577216085700433683675970442", + RefX: "19634304467424341201967588833358136184986895283932424931389373617195718495125", + RefY: "4505057526177196667324045514468194488213793428349311354897018598963999854450", + }, + { + U: "18564198753656528400088154276566130187716648544944996244887011101272723769966", + RefX: "3707034903888679703713199674918466665060250736106295976834456800686844552093", + RefY: "20676243876734662663067052459719992658277039396206884818959823964736875218440", + }, + { + U: "12148664457256947639632540629404870841722525175035414727813021084528407888462", + RefX: "18367015694244635550022423807179253069661899168470867641756530246141066291149", + RefY: "15905492037520064959928294149867899057581644385087020175633252278261850397170", + }, + { + U: "12093770217351553395851799744560073387542408411948793415811016030320000408954", + RefX: "18628637108052813525026927119117708071178789601878155364318000661242621962348", + RefY: "6040770983795260405158219606248686313662252842940408369820001204601020778736", + }, + { + U: "13942734143169598241551270500147294655037968401910290167032324334966573048878", + RefX: "20306468525308792577027609152697775212363369065665287007796518874644819462547", + RefY: "2214513985380114912440777388851425535506502591742613515234896241567322284028", + }, + { + U: "5763759726285226639910637491922035680430825809306960489557960428463370622298", + RefX: "17899292937287658511210513162099049043606535040705720211853528847584850234392", + RefY: "11537894058986146673734358059376459950947529743513515368017623860417811875170", + }, + { + U: "19921521412271807608695921806465035350856755723524829500302642290448989691589", + RefX: "17554704183346735278438770469711356748117041556911154446592515771155402856144", + RefY: "20761314222701992106820080593763904758233071525752609268700927463635753155547", + }, + { + U: "14229891363863137146747782282917951895500638857951329680815556449465500935181", + RefX: "18202607783713762835747034907461454806042157390240381890543442866394482248249", + RefY: "13757186455509128240067116514609284981267056536232159458277133179265244041669", + }, + { + U: "18472513948884699293539845917443564469459495591529692542730128865621006889860", + RefX: "1103374790491664039522273978616778956790128373945965882722575096257839199210", + RefY: "19296692309977538364091210479321258016027124590496028823778936392474366745046", + }, + { + U: "16072134618879048343930065257674741954353784195300713746334501368105987951238", + RefX: "8961618400274056198572834127581877058549705370402642715981787212376996250629", + RefY: "12200037427215655858779383214867329565502589290324416471641892412525026715612", + }, + { + U: "9426152769303899610281065078156914363854309269288129138214508611588957585431", + RefX: "13467279262430827153253724333017028479905694431377664102234622613064534219517", + RefY: "2936761746568599443299821607817750658964986051385259091966030429315637279537", + }, + { + U: "9254914835265828382226889379370928086699500581714968867179503650654420899360", + RefX: "21335904560494043949747568683074778032476761600458701376940814109724067321239", + RefY: "16647200754086283190771498445973027797321473168554634538073424288945676610494", + }, + { + U: "13386912969528419924561597653855522752766005324841002592315455865689387965358", + RefX: "84826530016659806879248525191624419224216136776153850602575939846033232778", + RefY: "16122644602027313153816033212781866714576928685337490527606433166045869294886", + }, + { + U: "12006152986615074577537072613341553652982820766447724962582899531996121255307", + RefX: "15036849546214838693108478088980721355314394032935287485974669189949907752001", + RefY: "6696864739013915138650604301970485354528427306684272732766283777119135225861", + }, + { + U: "17797502438783154336410968800649652912342600378370094392793526289627992454024", + RefX: "17568527467591213903729393964621588672705237355141152227866078590203870323770", + RefY: "1151776550182235516308019534599406056238991798395748971184360514265639669504", + }, + { + U: "15709216388666373044221627105289486066288503758778741192379854307726165102411", + RefX: "14744586843054605464427208718467606789731470982777136557449403740219693327286", + RefY: "3770472696248111355047652959888785612202726398630210013941989471263727016091", + }, + { + U: "5836537983721084500972681696123192854939186052038440361739851302520464428406", + RefX: "5155999237072319582312017324555828618491298459288847850951439671557760268657", + RefY: "6459565033258261915814768452672993299016728690762288790224283410121182510014", + }, + { + U: "17544678051619855238150458878806557408302734701884970297926882316807398903716", + RefX: "19789982035176094967109448237389851036114027977984965403304047721940537312919", + RefY: "12459148625581378698086782674037683194363712230649348864028373383418301475282", + }, + { + U: "9221178771391618631394606504197348605345596657606058256681802718749808514414", + RefX: "16360653441501907335919970268142432899194369499410864175190088661319300583390", + RefY: "7821567073333075665365210377836967277719680838614789096894945087565101546814", + }, +} diff --git a/pairing/bn254/twist.go b/pairing/bn254/twist.go new file mode 100644 index 000000000..69f58e6dd --- /dev/null +++ b/pairing/bn254/twist.go @@ -0,0 +1,217 @@ +package bn254 + +import ( + "math/big" +) + +// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are +// kept in Jacobian form and t=z² when valid. The group G₂ is the set of +// n-torsion points of this curve over GF(p²) (where n = Order) +type twistPoint struct { + x, y, z, t gfP2 +} + +var twistB = &gfP2{ + gfP{0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d}, + gfP{0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d}, +} + +// twistGen is the generator of group G₂. +var twistGen = &twistPoint{ + gfP2{ + gfP{0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b}, + gfP{0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b}, + }, + gfP2{ + gfP{0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482}, + gfP{0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206}, + }, + gfP2{*newGFp(0), *newGFp(1)}, + gfP2{*newGFp(0), *newGFp(1)}, +} + +func (c *twistPoint) String() string { + cpy := c.Clone() + cpy.MakeAffine() + x, y := gfP2Decode(&cpy.x), gfP2Decode(&cpy.y) + return "(" + x.String() + ", " + y.String() + ")" +} + +func (c *twistPoint) Set(a *twistPoint) { + c.x.Set(&a.x) + c.y.Set(&a.y) + c.z.Set(&a.z) + c.t.Set(&a.t) +} + +// IsOnCurve returns true iff c is on the curve. +func (c *twistPoint) IsOnCurve() bool { + c.MakeAffine() + if c.IsInfinity() { + return true + } + + y2, x3 := &gfP2{}, &gfP2{} + y2.Square(&c.y) + x3.Square(&c.x).Mul(x3, &c.x).Add(x3, twistB) + + if *y2 != *x3 { + return false + } + cneg := &twistPoint{} + cneg.Mul(c, Order) + return cneg.z.IsZero() +} + +func (c *twistPoint) SetInfinity() { + c.x.SetZero() + c.y.SetOne() + c.z.SetZero() + c.t.SetZero() +} + +func (c *twistPoint) IsInfinity() bool { + return c.z.IsZero() +} + +func (c *twistPoint) Add(a, b *twistPoint) { + // For additional comments, see the same function in curve.go. + + if a.IsInfinity() { + c.Set(b) + return + } + if b.IsInfinity() { + c.Set(a) + return + } + + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 + z12 := (&gfP2{}).Square(&a.z) + z22 := (&gfP2{}).Square(&b.z) + u1 := (&gfP2{}).Mul(&a.x, z22) + u2 := (&gfP2{}).Mul(&b.x, z12) + + t := (&gfP2{}).Mul(&b.z, z22) + s1 := (&gfP2{}).Mul(&a.y, t) + + t.Mul(&a.z, z12) + s2 := (&gfP2{}).Mul(&b.y, t) + + h := (&gfP2{}).Sub(u2, u1) + xEqual := h.IsZero() + + t.Add(h, h) + i := (&gfP2{}).Square(t) + j := (&gfP2{}).Mul(h, i) + + t.Sub(s2, s1) + yEqual := t.IsZero() + if xEqual && yEqual { + c.Double(a) + return + } + r := (&gfP2{}).Add(t, t) + + v := (&gfP2{}).Mul(u1, i) + + t4 := (&gfP2{}).Square(r) + t.Add(v, v) + t6 := (&gfP2{}).Sub(t4, j) + c.x.Sub(t6, t) + + t.Sub(v, &c.x) // t7 + t4.Mul(s1, j) // t8 + t6.Add(t4, t4) // t9 + t4.Mul(r, t) // t10 + c.y.Sub(t4, t6) + + t.Add(&a.z, &b.z) // t11 + t4.Square(t) // t12 + t.Sub(t4, z12) // t13 + t4.Sub(t, z22) // t14 + c.z.Mul(t4, h) +} + +func (c *twistPoint) Double(a *twistPoint) { + // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 + A := (&gfP2{}).Square(&a.x) + B := (&gfP2{}).Square(&a.y) + C := (&gfP2{}).Square(B) + + t := (&gfP2{}).Add(&a.x, B) + t2 := (&gfP2{}).Square(t) + t.Sub(t2, A) + t2.Sub(t, C) + d := (&gfP2{}).Add(t2, t2) + t.Add(A, A) + e := (&gfP2{}).Add(t, A) + f := (&gfP2{}).Square(e) + + t.Add(d, d) + c.x.Sub(f, t) + + c.z.Mul(&a.y, &a.z) + c.z.Add(&c.z, &c.z) + + t.Add(C, C) + t2.Add(t, t) + t.Add(t2, t2) + c.y.Sub(d, &c.x) + t2.Mul(e, &c.y) + c.y.Sub(t2, t) +} + +func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) { + sum, t := &twistPoint{}, &twistPoint{} + + for i := scalar.BitLen(); i >= 0; i-- { + t.Double(sum) + if scalar.Bit(i) != 0 { + sum.Add(t, a) + } else { + sum.Set(t) + } + } + + c.Set(sum) +} + +func (c *twistPoint) MakeAffine() { + if c.z.IsOne() { + return + } else if c.z.IsZero() { + c.x.SetZero() + c.y.SetOne() + c.t.SetZero() + return + } + + zInv := (&gfP2{}).Invert(&c.z) + t := (&gfP2{}).Mul(&c.y, zInv) + zInv2 := (&gfP2{}).Square(zInv) + c.y.Mul(t, zInv2) + t.Mul(&c.x, zInv2) + c.x.Set(t) + c.z.SetOne() + c.t.SetOne() +} + +func (c *twistPoint) Neg(a *twistPoint) { + c.x.Set(&a.x) + c.y.Neg(&a.y) + c.z.Set(&a.z) + c.t.SetZero() +} + +// Clone makes a hard copy of the point +func (c *twistPoint) Clone() *twistPoint { + n := &twistPoint{ + x: c.x.Clone(), + y: c.y.Clone(), + z: c.z.Clone(), + t: c.t.Clone(), + } + + return n +} diff --git a/pairing/bn254/util.go b/pairing/bn254/util.go new file mode 100644 index 000000000..220a77f93 --- /dev/null +++ b/pairing/bn254/util.go @@ -0,0 +1,13 @@ +package bn254 + +import "bytes" + +func zeroPadBytes(m []byte, outlen int) []byte { + if len(m) < outlen { + padlen := outlen - len(m) + out := bytes.NewBuffer(make([]byte, padlen, outlen)) + out.Write(m) + return out.Bytes() + } + return m +}