Skip to content

Commit

Permalink
handle oddball edge case for g1Add and proactively for g1Mul, add tes…
Browse files Browse the repository at this point in the history
…t case, make tests pickier about expected errors (#185)

Signed-off-by: garyschulte <garyschulte@gmail.com>
  • Loading branch information
garyschulte authored Jul 1, 2024
1 parent bf0b8e2 commit b108fd3
Show file tree
Hide file tree
Showing 20 changed files with 109 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ input,result,gas,notes
16eea4cc6a5c21b361c4d144f81f0c5774181b19b6341ebc3317b6d9c78b493407abc49d40a88a2336ea698f6bcc5b767f290fa5255f1ea9c449237dfa75259210264114425d52ebb998a32b103fe50d3c44b156f53dd16fec92c805c51b3bc117986b497207e3198ca7beb705537ba0d6c82cb8e6e1c507e74dece3fbb17fc2,2ef81763011baa4945a15da4c312cd2c280017994fcbea76048907c58acaf8f01a66e2bd9a4c4e1ca39a7fa9ba43f615c3720ae73c0d2aa6b2cb14e5a24f233d,150,
1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea0e9729271df80f9967d618c33d9e8389bd4afb88e8b1e26e20b98868406da8ce1aca0647ae2e8573e39970f442aa3900175beeef2984af814fa51cf4ab59e07c,278782b7f77402d99c21f0bb831e899431703967252026abb6a6cfefd6d368600bd99290fca19622267066ee211842111904f2ced987023a34048236be757231,150,
1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea,150,
1234,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, Point 0 is not on curve
1234,,150,invalid input parameters, Point 0 is not on curve
0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, Point 1 is not on curve
67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, Failed to parse Fp element
,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,
ff000000000000000000000000000000000000000000000000000000000000ff,,150,invalid input parameters, Failed to parse Fp element
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ input,result,gas,notes
1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab06c79809aa4a4be3391c4d41d5a6e62ca0a73a5b559cd0384ca11d444e34f40e04f2080483db9e54ae09e44ec19c26a1,1147da8fc5774b5ef94fda682437b04f9b6aea72987d1269496769baf7e67dc729fe144eab44c6da4c851123165cd6506ce3e10b7691b8bf11b757e2ae058fcb,6000,
0d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f950297768,0be6d75e2fe2887835d396dae11321ca7c53083abd6a0b270ee1c087593517aa2ffd1bad577de7cf2b19b82bfff0c66e2afbfb79a72cbe834290437f3caf2f21,6000,
d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid input parameters, Failed to parse Fp element
1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab,,6000,invalid input parameters
,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000,
1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60100000000000000000000000000000000,0x220cb1540fa85ba04d863dca86de9359a43ac9fc084aebb9f2a936d989abbb602ccdc6c020dd2cf78332132b3f1d1122391b515035623cd6f53d4aea24ea2466,6000,
1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60000000000000000000000000000000100000000000000000000000000000000,1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b,6000,
116 changes: 87 additions & 29 deletions gnark/gnark-jni/gnark-eip-196.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
"github.com/consensys/gnark-crypto/ecc/bn254/fp"
)

var ErrMalformedPoint = errors.New("invalid input parameters, invalid point encoding")
var ErrPointNotInField = errors.New("invalid input parameters, point not in field")
var ErrPointOnCurveCheckFailed = errors.New("invalid point: point is not on curve")

const (
EIP196PreallocateForResult = 128
EIP196PreallocateForError = 256
Expand All @@ -26,9 +30,14 @@ const (
EIP196PreallocateForG2 = EIP196PreallocateForG1 * 2 // G2 points are encoded as 2 concatenated G1 points
)

var ErrSubgroupCheckFailed = errors.New("invalid point: subgroup check failed")
var ErrPointOnCurveCheckFailed = errors.New("invalid point: point is not on curve")
var ErrMalformedOutputBytes = errors.New("malformed output buffer parameter")

// bn254Modulus is the value 21888242871839275222246405745257275088696311157297823662689037894645226208583
var bn254Modulus = new(big.Int).SetBytes([]byte{
0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29,
0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81, 0x58, 0x5d,
0x97, 0x81, 0x6a, 0x91, 0x68, 0x71, 0xca, 0x8d,
0x3c, 0x20, 0x8c, 0x16, 0xd8, 0x7c, 0xfd, 0x47,
})

// Predefine a zero slice of length 16
var zeroSlice = make([]byte, 16)
Expand All @@ -38,29 +47,37 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp
inputLen := int(cInputLen)
errorLen := int(cErrorLen)


if (inputLen > 2*EIP196PreallocateForG1) {
// trunc if input too long
inputLen = 2*EIP196PreallocateForG1
}

if inputLen < EIP196PreallocateForG1 {
// if we do not have complete input, return 0
return 0
}

// Convert error C pointers to Go slices
errorBuf := castErrorBuffer(javaErrorBuf, errorLen)

// check we have input size sufficient for a G1Affine
if inputLen < EIP196PreallocateForG1 {

// if not, check the X point and return an error if it is in the field, edge case
if inputLen >= EIP196PreallocateForFp {
input := (*[EIP196PreallocateForFp]byte)(unsafe.Pointer(javaInputBuf))[:EIP196PreallocateForFp:EIP196PreallocateForFp]
if !checkInField(input[:EIP196PreallocateForFp]) {
copy(errorBuf, ErrPointNotInField.Error())
return 1
}
}
// otherwise if we do not have complete input, return 0
return 0
}

// Convert input C pointers to Go slices
input := (*[2*EIP196PreallocateForG1]byte)(unsafe.Pointer(javaInputBuf))[:inputLen:inputLen]

// generate p0 g1 affine
var p0 bn254.G1Affine
err := p0.Unmarshal(input[:64])
p0, err := safeUnmarshal(input[:64])

if err != nil {
copy(errorBuf, err.Error())
copy(errorBuf, "invalid input parameters, " + err.Error())
return 1
}

Expand All @@ -69,20 +86,24 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp
if isAllZero(input[64:inputLen]) {
ret := p0.Marshal()
g1AffineEncode(ret, javaOutputBuf)
return 0;
} else {
// else return an incomplete input error
copy(errorBuf, ErrMalformedPoint.Error())
return 1
}
return 0;
}

// generate p1 g1 affine
var p1 bn254.G1Affine
err = p1.Unmarshal(input[64:])
p1, err := safeUnmarshal(input[64:])

if err != nil {
copy(errorBuf, err.Error())
copy(errorBuf, "invalid input parameters, " + err.Error())
return 1
}

// Use the Add method to combine points
result := p0.Add(&p0, &p1)
result := p0.Add(p0, p1)

// marshal the resulting point and encode directly to the output buffer
ret := result.Marshal()
Expand All @@ -100,7 +121,17 @@ func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp
errorBuf := castErrorBuffer(javaErrorBuf, errorLen)

if inputLen < EIP196PreallocateForG1 {
// if we do not have complete input, return 0

// check the X point and return an error if it is in the field, edge case
if inputLen >= EIP196PreallocateForFp {
input := (*[EIP196PreallocateForFp]byte)(unsafe.Pointer(javaInputBuf))[:EIP196PreallocateForFp:EIP196PreallocateForFp]
if !checkInField(input[:EIP196PreallocateForFp]) {
copy(errorBuf, ErrPointNotInField.Error())
return 1
}
}

// otherwise if we do not have complete input, return 0
return 0
}

Expand Down Expand Up @@ -226,6 +257,43 @@ func g1AffineEncode(g1Point []byte, output *C.char) (error) {
return nil
}

func safeUnmarshal(input []byte) (*bn254.G1Affine, error) {
var g1 bn254.G1Affine
err := g1.X.SetBytesCanonical(input[:32])
if (err == nil) {
err := g1.Y.SetBytesCanonical(input[32:64])
if (err == nil) {
return &g1, nil
}
}
if (!g1.IsOnCurve()) {
return nil, ErrPointOnCurveCheckFailed
}

return nil, err
}

// checkInField checks that an element is in the field, not-in-field will normally
// be caught during unmarshal, but here in case of no-op calls of a single parameter
func checkInField(data []byte) bool {

// Convert the byte slice to a big.Int
elem := new(big.Int).SetBytes(data)

// Compare the value to the bn254Modulus
return bn254Modulus.Cmp(elem) == 1
}

// isAllZero checks if all elements in the byte slice are zero
func isAllZero(data []byte) bool {
for _, b := range data {
if b != 0 {
return false
}
}
return true
}

func castBufferToSlice(buf unsafe.Pointer, length int) []byte {
var slice []byte
// Obtain the slice header
Expand Down Expand Up @@ -253,9 +321,6 @@ func castErrorBuffer(javaOutputBuf *C.char, length int) []byte {
return (*[EIP196PreallocateForError]byte)(unsafe.Pointer(javaOutputBuf))[:bufSize:bufSize]
}

func main() {
}

// generate g1Add test data suitable for unit test input csv
func generateTestDataForAdd() {
// generate a point from a field element
Expand Down Expand Up @@ -311,12 +376,5 @@ func Uint256ToStringBigEndian(number *big.Int) string {
return hex.EncodeToString(bytes)
}

// isAllZero checks if all elements in the byte slice are zero
func isAllZero(data []byte) bool {
for _, b := range data {
if b != 0 {
return false
}
}
return true
func main() {
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public void shouldCalculate() {
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ input,result,gas,notes
16eea4cc6a5c21b361c4d144f81f0c5774181b19b6341ebc3317b6d9c78b493407abc49d40a88a2336ea698f6bcc5b767f290fa5255f1ea9c449237dfa75259210264114425d52ebb998a32b103fe50d3c44b156f53dd16fec92c805c51b3bc117986b497207e3198ca7beb705537ba0d6c82cb8e6e1c507e74dece3fbb17fc2,2ef81763011baa4945a15da4c312cd2c280017994fcbea76048907c58acaf8f01a66e2bd9a4c4e1ca39a7fa9ba43f615c3720ae73c0d2aa6b2cb14e5a24f233d,150,
1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea0e9729271df80f9967d618c33d9e8389bd4afb88e8b1e26e20b98868406da8ce1aca0647ae2e8573e39970f442aa3900175beeef2984af814fa51cf4ab59e07c,278782b7f77402d99c21f0bb831e899431703967252026abb6a6cfefd6d368600bd99290fca19622267066ee211842111904f2ced987023a34048236be757231,150,
1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea,150,
1234,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid input length for G1 addition
0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid input length for G1 addition
67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid infinity point encoding
1234,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,
0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid point encoding
67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, invalid fp.Element encoding
,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,
ff000000000000000000000000000000000000000000000000000000000000ff,,150,invalid input parameters, point not in field
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ input,result,gas,notes
1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab06c79809aa4a4be3391c4d41d5a6e62ca0a73a5b559cd0384ca11d444e34f40e04f2080483db9e54ae09e44ec19c26a1,1147da8fc5774b5ef94fda682437b04f9b6aea72987d1269496769baf7e67dc729fe144eab44c6da4c851123165cd6506ce3e10b7691b8bf11b757e2ae058fcb,6000,
0d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f950297768,0be6d75e2fe2887835d396dae11321ca7c53083abd6a0b270ee1c087593517aa2ffd1bad577de7cf2b19b82bfff0c66e2afbfb79a72cbe834290437f3caf2f21,6000,
d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid compressed coordinate
1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000,invalid input parameters,
1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000,
,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000,
1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60100000000000000000000000000000000,0x220cb1540fa85ba04d863dca86de9359a43ac9fc084aebb9f2a936d989abbb602ccdc6c020dd2cf78332132b3f1d1122391b515035623cd6f53d4aea24ea2466,6000,
1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60000000000000000000000000000000100000000000000000000000000000000,1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b,6000,

0 comments on commit b108fd3

Please sign in to comment.