github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/merkletree/key.go (about)

     1  package merkletree
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	poseidon "github.com/iden3/go-iden3-crypto/goldenposeidon"
     9  )
    10  
    11  // Key stores key of the leaf
    12  type Key [32]byte
    13  
    14  const (
    15  	// HashPoseidonAllZeroes represents the poseidon hash for an input with all
    16  	// bits set to zero.
    17  	HashPoseidonAllZeroes = "0xc71603f33a1144ca7953db0ab48808f4c4055e3364a246c33c18a9786cb0b359"
    18  )
    19  
    20  // keyEthAddr is the common code for all the keys related to ethereum addresses.
    21  func keyEthAddr(ethAddr common.Address, leafType leafType, key1Capacity [4]uint64) ([]byte, error) {
    22  	ethAddrBI := new(big.Int).SetBytes(ethAddr.Bytes())
    23  	ethAddrArr := scalar2fea(ethAddrBI)
    24  
    25  	key1 := [8]uint64{
    26  		ethAddrArr[0],
    27  		ethAddrArr[1],
    28  		ethAddrArr[2],
    29  		ethAddrArr[3],
    30  		ethAddrArr[4],
    31  		0,
    32  		uint64(leafType),
    33  		0,
    34  	}
    35  
    36  	result, err := poseidon.Hash(key1, key1Capacity)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	return h4ToFilledByteSlice(result[:]), nil
    42  }
    43  
    44  func defaultCapIn() ([4]uint64, error) {
    45  	capIn, err := StringToh4(HashPoseidonAllZeroes)
    46  	if err != nil {
    47  		return [4]uint64{}, err
    48  	}
    49  
    50  	return [4]uint64{capIn[0], capIn[1], capIn[2], capIn[3]}, nil
    51  }
    52  
    53  // KeyEthAddrBalance returns the key of balance leaf:
    54  // hk0: H([0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0])
    55  // key: H([ethAddr[0:4], ethAddr[4:8], ethAddr[8:12], ethAddr[12:16], ethAddr[16:20], 0, 0, 0], [hk0[0], hk0[1], hk0[2], hk0[3]])
    56  func KeyEthAddrBalance(ethAddr common.Address) ([]byte, error) {
    57  	capIn, err := defaultCapIn()
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	return keyEthAddr(ethAddr, LeafTypeBalance, capIn)
    63  }
    64  
    65  // KeyEthAddrNonce returns the key of nonce leaf:
    66  // hk0: H([0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0])
    67  // key: H([ethAddr[0:4], ethAddr[4:8], ethAddr[8:12], ethAddr[12:16], ethAddr[16:20], 0, 1, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]
    68  func KeyEthAddrNonce(ethAddr common.Address) ([]byte, error) {
    69  	capIn, err := defaultCapIn()
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	return keyEthAddr(ethAddr, LeafTypeNonce, capIn)
    75  }
    76  
    77  // KeyContractCode returns the key of contract code leaf:
    78  // hk0: H([0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0])
    79  // key: H([ethAddr[0:4], ethAddr[4:8], ethAddr[8:12], ethAddr[12:16], ethAddr[16:20], 0, 2, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]
    80  func KeyContractCode(ethAddr common.Address) ([]byte, error) {
    81  	capIn, err := defaultCapIn()
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	return keyEthAddr(ethAddr, LeafTypeCode, capIn)
    87  }
    88  
    89  // KeyContractStorage returns the key of contract storage position leaf:
    90  // hk0: H([stoPos[0:4], stoPos[4:8], stoPos[8:12], stoPos[12:16], stoPos[16:20], stoPos[20:24], stoPos[24:28], stoPos[28:32], [0, 0, 0, 0])
    91  // key: H([ethAddr[0:4], ethAddr[4:8], ethAddr[8:12], ethAddr[12:16], ethAddr[16:20], 0, 3, 0], [hk0[0], hk0[1], hk0[2], hk0[3])
    92  func KeyContractStorage(ethAddr common.Address, storagePos []byte) ([]byte, error) {
    93  	storageBI := new(big.Int).SetBytes(storagePos)
    94  
    95  	storageArr := scalar2fea(storageBI)
    96  
    97  	hk0, err := poseidon.Hash([8]uint64{
    98  		storageArr[0],
    99  		storageArr[1],
   100  		storageArr[2],
   101  		storageArr[3],
   102  		storageArr[4],
   103  		storageArr[5],
   104  		storageArr[6],
   105  		storageArr[7],
   106  	}, [4]uint64{})
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	return keyEthAddr(ethAddr, LeafTypeStorage, hk0)
   112  }
   113  
   114  // hashContractBytecode computes the bytecode hash in order to add it to the
   115  // state-tree.
   116  func hashContractBytecode(code []byte) ([]uint64, error) {
   117  	const (
   118  		bytecodeElementsHash = 8
   119  		bytecodeBytesElement = 7
   120  
   121  		maxBytesToAdd = bytecodeElementsHash * bytecodeBytesElement
   122  	)
   123  
   124  	// add 0x01
   125  	code = append(code, 0x01) // nolint:gomnd
   126  
   127  	// add padding
   128  	for len(code)%(56) != 0 { // nolint:gomnd
   129  		code = append(code, 0x00) // nolint:gomnd
   130  	}
   131  
   132  	code[len(code)-1] = code[len(code)-1] | 0x80 // nolint:gomnd
   133  
   134  	numHashes := int(math.Ceil(float64(len(code)) / float64(maxBytesToAdd)))
   135  
   136  	tmpHash := [4]uint64{}
   137  	var err error
   138  
   139  	bytesPointer := 0
   140  	for i := 0; i < numHashes; i++ {
   141  		elementsToHash := [12]uint64{}
   142  
   143  		for j := 0; j < 4; j++ {
   144  			elementsToHash[j] = tmpHash[j]
   145  		}
   146  
   147  		subsetBytecode := code[bytesPointer : int(math.Min(float64(len(code)-1), float64(bytesPointer+maxBytesToAdd)))+1]
   148  		bytesPointer += maxBytesToAdd
   149  		tmpElem := [7]byte{}
   150  		counter := 0
   151  		index := 4
   152  		for j := 0; j < maxBytesToAdd; j++ {
   153  			byteToAdd := []byte{0}
   154  
   155  			if j < len(subsetBytecode) {
   156  				byteToAdd = subsetBytecode[j : j+1]
   157  			}
   158  
   159  			tmpElem[bytecodeBytesElement-1-counter] = byteToAdd[0]
   160  			counter++
   161  
   162  			if counter == bytecodeBytesElement {
   163  				elementsToHash[index] = new(big.Int).SetBytes(tmpElem[:]).Uint64()
   164  				index++
   165  				tmpElem = [7]byte{}
   166  				counter = 0
   167  			}
   168  		}
   169  		tmpHash, err = poseidon.Hash([8]uint64{
   170  			elementsToHash[4],
   171  			elementsToHash[5],
   172  			elementsToHash[6],
   173  			elementsToHash[7],
   174  			elementsToHash[8],
   175  			elementsToHash[9],
   176  			elementsToHash[10],
   177  			elementsToHash[11],
   178  		}, [4]uint64{
   179  			elementsToHash[0],
   180  			elementsToHash[1],
   181  			elementsToHash[2],
   182  			elementsToHash[3],
   183  		})
   184  		if err != nil {
   185  			return nil, err
   186  		}
   187  	}
   188  	return tmpHash[:], nil
   189  }
   190  
   191  // KeyCodeLength returns the key of code length leaf:
   192  // hk0: H([0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0])
   193  // key: H([ethAddr[0:4], ethAddr[4:8], ethAddr[8:12], ethAddr[12:16], ethAddr[16:20], 0, 4, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]
   194  func KeyCodeLength(ethAddr common.Address) ([]byte, error) {
   195  	capIn, err := defaultCapIn()
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	return keyEthAddr(ethAddr, LeafTypeSCLength, capIn)
   201  }