diff --git a/contracts/ens/cid.go b/contracts/ens/cid.go
new file mode 100644
index 0000000000..bf19d1080c
--- /dev/null
+++ b/contracts/ens/cid.go
@@ -0,0 +1,114 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package ens
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+const (
+ ns_ipfs = 0xe3
+ ns_swarm = 0xe4
+
+ swarm_typecode = 0x99 //todo change
+ swarm_hashtype = 0x1b //todo change
+
+ ipfs_hashtype = 0x12
+
+ hash_length = 32
+)
+
+// deocodeEIP1577ContentHash decodes a chain-stored content hash from an ENS record according to EIP-1577
+// a successful decode will result the different parts of the content hash in accordance to the CID spec
+// Note: only CIDv1 is supported
+func decodeEIP1577ContentHash(buf []byte) (storageNs, contentType, hashType, hashLength uint64, hash []byte, err error) {
+ if len(buf) < 10 {
+ return 0, 0, 0, 0, nil, fmt.Errorf("buffer too short")
+ }
+
+ storageNs, n := binary.Uvarint(buf)
+
+ buf = buf[n:]
+ vers, n := binary.Uvarint(buf)
+
+ if vers != 1 {
+ return 0, 0, 0, 0, nil, fmt.Errorf("expected cid v1, got: %d", vers)
+ }
+ buf = buf[n:]
+ contentType, n = binary.Uvarint(buf)
+
+ buf = buf[n:]
+ hashType, n = binary.Uvarint(buf)
+
+ buf = buf[n:]
+ hashLength, n = binary.Uvarint(buf)
+
+ hash = buf[n:]
+
+ if len(hash) != int(hashLength) {
+ return 0, 0, 0, 0, nil, errors.New("hash length mismatch")
+ }
+ return storageNs, contentType, hashType, hashLength, hash, nil
+}
+
+func extractContentHash(buf []byte) (common.Hash, error) {
+ storageNs, contentType, hashType, hashLength, hashBytes, err := decodeEIP1577ContentHash(buf)
+
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ if storageNs != ns_swarm {
+ return common.Hash{}, errors.New("unknown storage system")
+ }
+
+ if contentType != swarm_typecode { //todo pending pr
+ return common.Hash{}, errors.New("unknown content type")
+ }
+
+ if hashType != swarm_hashtype { //todo: should be bmt
+ return common.Hash{}, errors.New("unknown multihash type")
+ }
+
+ if hashLength != hash_length {
+ return common.Hash{}, errors.New("odd hash length, swarm expects 32 bytes")
+ }
+
+ if len(hashBytes) != int(hashLength) {
+ return common.Hash{}, errors.New("hash length mismatch")
+ }
+
+ return common.BytesToHash(buf), nil
+}
+
+// encodeCid encodes a swarm hash into an IPLD CID
+/*func encodeCid(h common.Hash) (cid.Cid, error) {
+ b := []byte{0x1b, 0x20} //0x1b = keccak256 (should be changed to bmt), 0x20 = 32 bytes hash length
+ b = append(b, h.Bytes()...) // append actual hash bytes
+ multi, err := mh.Cast(b)
+ if err != nil {
+ return cid.Cid{}, err
+ }
+
+ c := cid.NewCidV1(cid.Raw, multi) //todo: cid.Raw should be swarm manifest
+
+ return c, nil
+}*/
diff --git a/contracts/ens/cid_test.go b/contracts/ens/cid_test.go
new file mode 100644
index 0000000000..8ee4f1b5ca
--- /dev/null
+++ b/contracts/ens/cid_test.go
@@ -0,0 +1,200 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package ens
+
+import (
+ "bytes"
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Tests for the decoding of the example ENS
+func TestEIPSpecCidDecode(t *testing.T) {
+ const (
+ eipSpecHash = "e3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
+ eipHash = "29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
+
+ dag_pb = 0x70
+ sha2_256 = 0x12
+ )
+
+ b, err := hex.DecodeString(eipSpecHash)
+ if err != nil {
+ t.Fatal(err)
+ }
+ hashBytes, err := hex.DecodeString(eipHash)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ storageNs, contentType, hashType, hashLength, hashBytes, err := decodeEIP1577ContentHash(b)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ if storageNs != ns_ipfs {
+ t.Fatal("wrong ns")
+ }
+ if contentType != dag_pb {
+ t.Fatal("should be swarm typecode")
+ }
+ if hashType != sha2_256 {
+ t.Fatal("should be sha2-256")
+ }
+ if hashLength != 32 {
+ t.Fatal("should be 32")
+ }
+ if !bytes.Equal(hashBytes, hashBytes) {
+ t.Fatal("should be equal")
+ }
+
+}
+func TestManualCidDecode(t *testing.T) {
+ // call cid encode method with hash. expect byte slice returned, compare according to spec
+ bb := []byte{}
+
+ for _, v := range []struct {
+ name string
+ headerBytes []byte
+ fails bool
+ }{
+ {
+ name: "values correct, should not fail",
+ headerBytes: []byte{0xe4, 0x01, 0x99, 0x1b, 0x20},
+ fails: false,
+ },
+ {
+ name: "cid version wrong, should fail",
+ headerBytes: []byte{0xe4, 0x00, 0x99, 0x1b, 0x20},
+ fails: true,
+ },
+ {
+ name: "hash length wrong, should fail",
+ headerBytes: []byte{0xe4, 0x01, 0x99, 0x1b, 0x1f},
+ fails: true,
+ },
+ {
+ name: "values correct for ipfs, should fail",
+ headerBytes: []byte{0xe3, 0x01, 0x99, 0x1b, 0x20},
+ fails: true,
+ },
+ } {
+ t.Run(v.name, func(t *testing.T) {
+ buf := make([]byte, binary.MaxVarintLen64)
+ for _, vv := range v.headerBytes {
+ n := binary.PutUvarint(buf, uint64(vv))
+ bb = append(bb, buf[:n]...)
+ }
+
+ h := common.HexToHash("29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f")
+ bb = append(bb, h[:]...)
+ str := hex.EncodeToString(bb)
+ fmt.Println(str)
+ decodedHash, e := extractContentHash(bb)
+ switch v.fails {
+ case true:
+ if e == nil {
+ t.Fatal("the decode should fail")
+ }
+ case false:
+ if e != nil {
+ t.Fatalf("the deccode shouldnt fail: %v", e)
+ }
+ if !bytes.Equal(decodedHash[:], h[:]) {
+ t.Fatal("hashes not equal")
+ }
+
+ }
+
+ })
+ }
+
+ /* from the EIP documentation
+ storage system: Swarm (0xe4)
+ CID version: 1 (0x01)
+ content type: swarm-manifest (0x??)
+ hash function: keccak-256 (0x1B)
+ hash length: 32 bytes (0x20)
+ hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
+ */
+
+}
+
+func TestManuelCidEncode(t *testing.T) {
+ // call cid encode method with hash. expect byte slice returned, compare according to spec
+
+ /* from the EIP documentation
+ storage system: Swarm (0xe4)
+ CID version: 1 (0x01)
+ content type: swarm-manifest (0x??)
+ hash function: keccak-256 (0x1B)
+ hash length: 32 bytes (0x20)
+ hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
+ */
+
+}
+
+/*
+func TestCIDSanity(t *testing.T) {
+ hashStr := "d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162"
+ hash := common.HexToHash(hashStr) //this always yields a 32 byte long hash
+ cc, err := encodeCid(hash)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if cc.Prefix().MhLength != 32 {
+ t.Fatal("w00t")
+ }
+ decoded, err := mh.Decode(cc.Hash())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if decoded.Length != 32 {
+ t.Fatal("invalid length")
+ }
+ if !bytes.Equal(decoded.Digest, hash[:]) {
+ t.Fatalf("hashes not equal")
+ }
+
+ if decoded.Length != 32 {
+ t.Fatal("wrong length")
+ }
+ fmt.Println(cc.StringOfBase(multibase.Base16))
+
+ bbbb, e := cc.StringOfBase(multibase.Base16)
+ if e != nil {
+ t.Fatal(e)
+ }
+ fmt.Println(bbbb)
+ //create the CID string artificially
+ hashStr = "f01551b20" + hashStr
+
+ c, err := cid.Decode(hashStr)
+ if err != nil {
+ t.Fatalf("Error decoding CID: %v", err)
+ }
+
+ fmt.Sprintf("Got CID: %v", c)
+ fmt.Println("Got CID:", c.Prefix())
+
+}*/
diff --git a/contracts/ens/ens.go b/contracts/ens/ens.go
index 4a910fcff9..bbca8f2028 100644
--- a/contracts/ens/ens.go
+++ b/contracts/ens/ens.go
@@ -23,8 +23,6 @@ package ens
import (
"encoding/binary"
- "errors"
- "fmt"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -262,61 +260,3 @@ func (ens *ENS) SetContentHash(name string, hash []byte) (*types.Transaction, er
// END DEPRECATED CODE
return resolver.Contract.SetContenthash(&opts, node, hash)
}
-
-func manualDecode(buf []byte) (common.Hash, error) {
- if len(buf) < 2 {
- return common.Hash{}, errors.New("buffer too short")
- }
-
- storageSys, n := binary.Uvarint(buf)
- if storageSys != 0xe3 && storageSys != 0xe4 {
- return common.Hash{}, errors.New("unknown storage system")
- }
- buf = buf[n:]
- vers, n := binary.Uvarint(buf)
-
- if vers != 1 {
- return common.Hash{}, fmt.Errorf("expected 1 as the cid version number, got: %d", vers)
- }
-
- buf = buf[n:]
- ctype, n := binary.Uvarint(buf)
-
- if ctype < 0 { // ctype != 0x99 {
- return common.Hash{}, errors.New("unknown content type")
- }
- buf = buf[n:]
- hashType, n := binary.Uvarint(buf)
-
- if hashType != 0x1b && hashType != 0x12 {
- return common.Hash{}, errors.New("unknown multihash type")
- }
-
- buf = buf[n:]
- hashLen, n := binary.Uvarint(buf)
-
- if hashLen != 32 {
- return common.Hash{}, errors.New("odd hash length, swarm expects 32 bytes")
- }
- buf = buf[n:]
-
- if len(buf) != int(hashLen) {
- return common.Hash{}, errors.New("hash length mismatch")
- }
-
- return common.BytesToHash(buf), nil
-}
-
-// encodeCid encodes a swarm hash into an IPLD CID
-/*func encodeCid(h common.Hash) (cid.Cid, error) {
- b := []byte{0x1b, 0x20} //0x1b = keccak256 (should be changed to bmt), 0x20 = 32 bytes hash length
- b = append(b, h.Bytes()...) // append actual hash bytes
- multi, err := mh.Cast(b)
- if err != nil {
- return cid.Cid{}, err
- }
-
- c := cid.NewCidV1(cid.Raw, multi) //todo: cid.Raw should be swarm manifest
-
- return c, nil
-}*/
diff --git a/contracts/ens/ens_test.go b/contracts/ens/ens_test.go
index e225238321..764a575cb7 100644
--- a/contracts/ens/ens_test.go
+++ b/contracts/ens/ens_test.go
@@ -17,10 +17,6 @@
package ens
import (
- "bytes"
- "encoding/binary"
- "encoding/hex"
- "fmt"
"math/big"
"testing"
@@ -124,169 +120,3 @@ func TestENS(t *testing.T) {
}
t.Fatal("todo: try to set old contract with new multicodec stuff and assert fail, set new contract with multicodec stuff, encode, decode and assert returns correct hash")
}
-
-func TestEIPSpecCidDecode(t *testing.T) {
- /*storage system: IPFS (0xe3)
- CID version: 1 (0x01)
- content type: dag-pb (0x70)
- hash function: sha2-256 (0x12)
- hash length: 32 bytes (0x20)
- hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
- */
-
- const eipSpecHash = "e3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
- const eipHash = "29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
-
- b, err := hex.DecodeString(eipSpecHash)
- if err != nil {
- t.Fatal(err)
- }
- hashBytes, err := hex.DecodeString(eipHash)
-
- if err != nil {
- t.Fatal(err)
- }
- h, err := manualDecode(b)
-
- if err != nil {
- t.Fatal(err)
- }
-
- if !bytes.Equal(h[:], hashBytes) {
- t.Fatal("should be equal")
- }
-
-}
-
-func TestManualCidDecode(t *testing.T) {
- // call cid encode method with hash. expect byte slice returned, compare according to spec
- bb := []byte{}
-
- for _, v := range []struct {
- name string
- headerBytes []byte
- fails bool
- }{
- {
- name: "values correct, should not fail",
- headerBytes: []byte{0xe4, 0x01, 0x99, 0x1b, 0x20},
- fails: false,
- },
- {
- name: "cid version wrong, should fail",
- headerBytes: []byte{0xe4, 0x01, 0x99, 0x1b, 0x20},
- fails: true,
- },
- {
- name: "hash length wrong, should fail",
- headerBytes: []byte{0xe4, 0x01, 0x99, 0x1b, 0x1f},
- fails: true,
- },
- {
- name: "values correct for ipfs, should fail",
- headerBytes: []byte{0xe3, 0x01, 0x99, 0x1b, 0x20},
- fails: true,
- },
- } {
- t.Run(v.name, func(t *testing.T) {
- buf := make([]byte, binary.MaxVarintLen64)
- for _, vv := range v.headerBytes {
- n := binary.PutUvarint(buf, uint64(vv))
- bb = append(bb, buf[:n]...)
- }
-
- h := common.HexToHash("29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f")
- bb = append(bb, h[:]...)
- str := hex.EncodeToString(bb)
- fmt.Println(str)
- decodedHash, e := manualDecode(bb)
- switch v.fails {
- case true:
- if e == nil {
- t.Fatal("the decode should fail")
- }
- case false:
- if e != nil {
- t.Fatal("the deccode shouldnt fail")
- }
- }
- if e != nil {
- t.Fatal(e)
- }
-
- if !bytes.Equal(decodedHash[:], h[:]) {
- t.Fatal("hashes not equal")
- }
- })
- }
-
- /* from the EIP documentation
- storage system: Swarm (0xe4)
- CID version: 1 (0x01)
- content type: swarm-manifest (0x??)
- hash function: keccak-256 (0x1B)
- hash length: 32 bytes (0x20)
- hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
- */
-
-}
-
-func TestManuelCidEncode(t *testing.T) {
- // call cid encode method with hash. expect byte slice returned, compare according to spec
-
- /* from the EIP documentation
- storage system: Swarm (0xe4)
- CID version: 1 (0x01)
- content type: swarm-manifest (0x??)
- hash function: keccak-256 (0x1B)
- hash length: 32 bytes (0x20)
- hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
- */
-
-}
-
-/*
-func TestCIDSanity(t *testing.T) {
- hashStr := "d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162"
- hash := common.HexToHash(hashStr) //this always yields a 32 byte long hash
- cc, err := encodeCid(hash)
- if err != nil {
- t.Fatal(err)
- }
-
- if cc.Prefix().MhLength != 32 {
- t.Fatal("w00t")
- }
- decoded, err := mh.Decode(cc.Hash())
- if err != nil {
- t.Fatal(err)
- }
- if decoded.Length != 32 {
- t.Fatal("invalid length")
- }
- if !bytes.Equal(decoded.Digest, hash[:]) {
- t.Fatalf("hashes not equal")
- }
-
- if decoded.Length != 32 {
- t.Fatal("wrong length")
- }
- fmt.Println(cc.StringOfBase(multibase.Base16))
-
- bbbb, e := cc.StringOfBase(multibase.Base16)
- if e != nil {
- t.Fatal(e)
- }
- fmt.Println(bbbb)
- //create the CID string artificially
- hashStr = "f01551b20" + hashStr
-
- c, err := cid.Decode(hashStr)
- if err != nil {
- t.Fatalf("Error decoding CID: %v", err)
- }
-
- fmt.Sprintf("Got CID: %v", c)
- fmt.Println("Got CID:", c.Prefix())
-
-}*/