github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/contracts/ens/cid.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package ens
    18  
    19  import (
    20  	"encoding/binary"
    21  	"errors"
    22  	"fmt"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  )
    26  
    27  const (
    28  	cidv1 = 0x1
    29  
    30  	nsIpfs  = 0xe3
    31  	nsSwarm = 0xe4
    32  
    33  	swarmTypecode = 0xfa // swarm manifest, see https://github.com/multiformats/multicodec/blob/master/table.csv
    34  	swarmHashtype = 0x1b // keccak256, see https://github.com/multiformats/multicodec/blob/master/table.csv
    35  
    36  	hashLength = 32
    37  )
    38  
    39  // deocodeEIP1577ContentHash decodes a chain-stored content hash from an ENS record according to EIP-1577
    40  // a successful decode will result the different parts of the content hash in accordance to the CID spec
    41  // Note: only CIDv1 is supported
    42  func decodeEIP1577ContentHash(buf []byte) (storageNs, contentType, hashType, hashLength uint64, hash []byte, err error) {
    43  	if len(buf) < 10 {
    44  		return 0, 0, 0, 0, nil, errors.New("buffer too short")
    45  	}
    46  
    47  	storageNs, n := binary.Uvarint(buf)
    48  
    49  	buf = buf[n:]
    50  	vers, n := binary.Uvarint(buf)
    51  
    52  	if vers != 1 {
    53  		return 0, 0, 0, 0, nil, fmt.Errorf("expected cid v1, got: %d", vers)
    54  	}
    55  	buf = buf[n:]
    56  	contentType, n = binary.Uvarint(buf)
    57  
    58  	buf = buf[n:]
    59  	hashType, n = binary.Uvarint(buf)
    60  
    61  	buf = buf[n:]
    62  	hashLength, n = binary.Uvarint(buf)
    63  
    64  	hash = buf[n:]
    65  
    66  	if len(hash) != int(hashLength) {
    67  		return 0, 0, 0, 0, nil, errors.New("hash length mismatch")
    68  	}
    69  	return storageNs, contentType, hashType, hashLength, hash, nil
    70  }
    71  
    72  func extractContentHash(buf []byte) (common.Hash, error) {
    73  	storageNs, _ /*contentType*/, _ /* hashType*/, decodedHashLength, hashBytes, err := decodeEIP1577ContentHash(buf)
    74  
    75  	if err != nil {
    76  		return common.Hash{}, err
    77  	}
    78  
    79  	if storageNs != nsSwarm {
    80  		return common.Hash{}, errors.New("unknown storage system")
    81  	}
    82  
    83  	//todo: for the time being we implement loose enforcement for the EIP rules until ENS manager is updated
    84  	/*if contentType != swarmTypecode {
    85  		return common.Hash{}, errors.New("unknown content type")
    86  	}
    87  
    88  	if hashType != swarmHashtype {
    89  		return common.Hash{}, errors.New("unknown multihash type")
    90  	}*/
    91  
    92  	if decodedHashLength != hashLength {
    93  		return common.Hash{}, errors.New("odd hash length, swarm expects 32 bytes")
    94  	}
    95  
    96  	if len(hashBytes) != int(hashLength) {
    97  		return common.Hash{}, errors.New("hash length mismatch")
    98  	}
    99  
   100  	return common.BytesToHash(buf), nil
   101  }
   102  
   103  func EncodeSwarmHash(hash common.Hash) ([]byte, error) {
   104  	var cidBytes []byte
   105  	var headerBytes = []byte{
   106  		nsSwarm,       //swarm namespace
   107  		cidv1,         // CIDv1
   108  		swarmTypecode, // swarm hash
   109  		swarmHashtype, // keccak256 hash
   110  		hashLength,    //hash length. 32 bytes
   111  	}
   112  
   113  	varintbuf := make([]byte, binary.MaxVarintLen64)
   114  	for _, v := range headerBytes {
   115  		n := binary.PutUvarint(varintbuf, uint64(v))
   116  		cidBytes = append(cidBytes, varintbuf[:n]...)
   117  	}
   118  
   119  	cidBytes = append(cidBytes, hash[:]...)
   120  	return cidBytes, nil
   121  }