Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Solidity Implementation #12

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@ module github.com/confio/ics23

go 1.14

require github.com/confio/ics23/go v0.0.0-20200804135649-a9fbc744ca3d // indirect
require (
github.com/ethereum/go-ethereum v1.10.0
github.com/gogo/protobuf v1.3.2
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
)
691 changes: 689 additions & 2 deletions go.sum

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions go/go.mod

This file was deleted.

14 changes: 0 additions & 14 deletions go/go.sum

This file was deleted.

184 changes: 14 additions & 170 deletions go/ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,92 +7,13 @@ import (
)

func TestLeafOp(t *testing.T) {
cases := map[string]struct {
op *LeafOp
key []byte
value []byte
isErr bool
expected []byte
}{
"hash foobar": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("foo"),
value: []byte("bar"),
// echo -n foobar | sha256sum
expected: fromHex("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"),
},
"hash foobaz, sha-512": {
op: &LeafOp{
Hash: HashOp_SHA512,
// no prehash, no length prefix
},
key: []byte("foo"),
value: []byte("baz"),
// echo -n foobaz | sha512sum
expected: fromHex("4f79f191298ec7461d60136c60f77c2ae8ddd85dbf6168bb925092d51bfb39b559219b39ae5385ba04946c87f64741385bef90578ea6fe6dac85dbf7ad3f79e1"),
},
"hash foobar (different break)": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("f"),
value: []byte("oobar"),
// echo -n foobar | sha256sum
expected: fromHex("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"),
},
"requires key": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
key: []byte("foo"),
isErr: true,
},
"requires value": {
op: &LeafOp{
Hash: HashOp_SHA256,
// no prehash, no length prefix
},
value: []byte("bar"),
isErr: true,
},
"hash with length prefix": {
op: &LeafOp{
Hash: HashOp_SHA256,
Length: LengthOp_VAR_PROTO,
// no prehash
},
// echo -n food | xxs -ps
// and manually compute length byte
key: []byte("food"), // 04666f6f64
value: []byte("some longer text"), // 10736f6d65206c6f6e6765722074657874
// echo -n 04666f6f6410736f6d65206c6f6e6765722074657874 | xxd -r -p | sha256sum
expected: fromHex("b68f5d298e915ae1753dd333da1f9cf605411a5f2e12516be6758f365e6db265"),
},
"hash with prehash and length prefix": {
op: &LeafOp{
Hash: HashOp_SHA256,
Length: LengthOp_VAR_PROTO,
PrehashValue: HashOp_SHA256,
},
key: []byte("food"), // 04666f6f64
// TODO: this is hash, then length....
// echo -n yet another long string | sha256sum
value: []byte("yet another long string"), // 20a48c2d4f67b9f80374938535285ed285819d8a5a8fc1fccd1e3244e437cf290d
// echo -n 04666f6f6420a48c2d4f67b9f80374938535285ed285819d8a5a8fc1fccd1e3244e437cf290d | xxd -r -p | sha256sum
expected: fromHex("87e0483e8fb624aef2e2f7b13f4166cda485baa8e39f437c83d74c94bedb148f"),
},
}
cases := LeafOpTestData()

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := tc.op.Apply(tc.key, tc.value)
res, err := tc.Op.Apply(tc.Key, tc.Value)
// short-circuit with error case
if tc.isErr {
if tc.IsErr {
if err == nil {
t.Fatal("Expected error, but got none")
}
Expand All @@ -102,63 +23,21 @@ func TestLeafOp(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(res, tc.expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.expected))
if !bytes.Equal(res, tc.Expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.Expected))
}
})
}
}

func TestInnerOp(t *testing.T) {
cases := map[string]struct {
op *InnerOp
child []byte
isErr bool
expected []byte
}{
"requires child": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("0123456789"),
Suffix: fromHex("deadbeef"),
},
isErr: true,
},
"hash child with prefix and suffix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("0123456789"),
Suffix: fromHex("deadbeef"),
},
child: fromHex("00cafe00"),
// echo -n 012345678900cafe00deadbeef | xxd -r -p | sha256sum
expected: fromHex("0339f76086684506a6d42a60da4b5a719febd4d96d8b8d85ae92849e3a849a5e"),
},
"hash child with only prefix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Prefix: fromHex("00204080a0c0e0"),
},
child: fromHex("ffccbb997755331100"),
// echo -n 00204080a0c0e0ffccbb997755331100 | xxd -r -p | sha256sum
expected: fromHex("45bece1678cf2e9f4f2ae033e546fc35a2081b2415edcb13121a0e908dca1927"),
},
"hash child with only suffix": {
op: &InnerOp{
Hash: HashOp_SHA256,
Suffix: []byte(" just kidding!"),
},
child: []byte("this is a sha256 hash, really...."),
// echo -n 'this is a sha256 hash, really.... just kidding!' | sha256sum
expected: fromHex("79ef671d27e42a53fba2201c1bbc529a099af578ee8a38df140795db0ae2184b"),
},
}
cases := InnerOpTestData()

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := tc.op.Apply(tc.child)
res, err := tc.Op.Apply(tc.Child)
// short-circuit with error case
if tc.isErr {
if tc.IsErr {
if err == nil {
t.Fatal("Expected error, but got none")
}
Expand All @@ -168,61 +47,26 @@ func TestInnerOp(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(res, tc.expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.expected))
if !bytes.Equal(res, tc.Expected) {
t.Errorf("Bad result: %s vs %s", toHex(res), toHex(tc.Expected))
}
})
}
}

func TestDoHash(t *testing.T) {
cases := map[string]struct {
hashOp HashOp
preimage string
expectedHash string
}{
"sha256": {
hashOp: HashOp_SHA256,
preimage: "food",
// echo -n food | sha256sum
expectedHash: "c1f026582fe6e8cb620d0c85a72fe421ddded756662a8ec00ed4c297ad10676b",
},
"ripemd160": {
hashOp: HashOp_RIPEMD160,
preimage: "food",
// echo -n food | openssl dgst -rmd160 -hex | cut -d' ' -f2
expectedHash: "b1ab9988c7c7c5ec4b2b291adfeeee10e77cdd46",
},
"bitcoin": {
hashOp: HashOp_BITCOIN,
preimage: "food",
// echo -n c1f026582fe6e8cb620d0c85a72fe421ddded756662a8ec00ed4c297ad10676b | xxd -r -p | openssl dgst -rmd160 -hex
expectedHash: "0bcb587dfb4fc10b36d57f2bba1878f139b75d24",
},
}
cases := DoHashTestData()

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
res, err := doHash(tc.hashOp, []byte(tc.preimage))
res, err := doHash(tc.HashOp, []byte(tc.Preimage))
if err != nil {
t.Fatal(err)
}
hexRes := hex.EncodeToString(res)
if hexRes != tc.expectedHash {
t.Fatalf("Expected %s got %s", tc.expectedHash, hexRes)
if hexRes != tc.ExpectedHash {
t.Fatalf("Expected %s got %s", tc.ExpectedHash, hexRes)
}
})
}
}

func fromHex(data string) []byte {
res, err := hex.DecodeString(data)
if err != nil {
panic(err)
}
return res
}

func toHex(data []byte) string {
return hex.EncodeToString(data)
}
Loading