diff --git a/fhevm/contracts_test.go b/fhevm/contracts_test.go
new file mode 100644
index 0000000..b4e1216
--- /dev/null
+++ b/fhevm/contracts_test.go
@@ -0,0 +1,3154 @@
+// Copyright 2014 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 fhevm
+
+import (
+ "math/big"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+func init() {
+ // register errors from geth so that tests recognize them
+ RegisterErrors(
+ vm.ErrOutOfGas,
+ vm.ErrCodeStoreOutOfGas,
+ vm.ErrDepth,
+ vm.ErrInsufficientBalance,
+ vm.ErrContractAddressCollision,
+ vm.ErrExecutionReverted,
+ vm.ErrMaxInitCodeSizeExceeded,
+ vm.ErrMaxCodeSizeExceeded,
+ vm.ErrInvalidJump,
+ vm.ErrWriteProtection,
+ vm.ErrReturnDataOutOfBounds,
+ vm.ErrGasUintOverflow,
+ vm.ErrInvalidCode,
+ vm.ErrNonceUintOverflow,
+ nil,
+ nil,
+ nil,
+ )
+}
+
+func toPrecompileInput(isScalar bool, hashes ...common.Hash) []byte {
+ ret := make([]byte, 0)
+ for _, hash := range hashes {
+ ret = append(ret, hash.Bytes()...)
+ }
+ var isScalarByte byte
+ if isScalar {
+ isScalarByte = 1
+ } else {
+ isScalarByte = 0
+ }
+ ret = append(ret, isScalarByte)
+ return ret
+}
+
+var scalarBytePadding = make([]byte, 31)
+
+func toLibPrecompileInput(method string, isScalar bool, hashes ...common.Hash) []byte {
+ ret := make([]byte, 0)
+ hashRes := crypto.Keccak256([]byte(method))
+ signature := hashRes[0:4]
+ ret = append(ret, signature...)
+ for _, hash := range hashes {
+ ret = append(ret, hash.Bytes()...)
+ }
+ var isScalarByte byte
+ if isScalar {
+ isScalarByte = 1
+ } else {
+ isScalarByte = 0
+ }
+ ret = append(ret, isScalarByte)
+ ret = append(ret, scalarBytePadding...)
+ return ret
+}
+
+func toLibPrecompileInputNoScalar(method string, hashes ...common.Hash) []byte {
+ ret := make([]byte, 0)
+ hashRes := crypto.Keccak256([]byte(method))
+ signature := hashRes[0:4]
+ ret = append(ret, signature...)
+ for _, hash := range hashes {
+ ret = append(ret, hash.Bytes()...)
+ }
+ return ret
+}
+
+func VerifyCiphertext(t *testing.T, fheUintType FheUintType) {
+ var value uint32
+ switch fheUintType {
+ case FheUint8:
+ value = 2
+ case FheUint16:
+ value = 4283
+ case FheUint32:
+ value = 1333337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ compact := encryptAndSerializeCompact(value, fheUintType)
+ input := append(compact, byte(fheUintType))
+ out, err := verifyCiphertextRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ ct := new(tfheCiphertext)
+ if err = ct.deserializeCompact(compact, fheUintType); err != nil {
+ t.Fatalf(err.Error())
+ }
+ if common.BytesToHash(out) != ct.getHash() {
+ t.Fatalf("output hash in verifyCipertext is incorrect")
+ }
+ res := getVerifiedCiphertextFromEVM(environment, ct.getHash())
+ if res == nil {
+ t.Fatalf("verifyCiphertext must have verified given ciphertext")
+ }
+}
+
+func VerifyCiphertextBadType(t *testing.T, actualType FheUintType, metadataType FheUintType) {
+ var value uint32
+ switch actualType {
+ case FheUint8:
+ value = 2
+ case FheUint16:
+ value = 4283
+ case FheUint32:
+ value = 1333337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ compact := encryptAndSerializeCompact(value, actualType)
+ input := append(compact, byte(metadataType))
+ _, err := verifyCiphertextRun(environment, addr, addr, input, readOnly)
+ if err == nil {
+ t.Fatalf("verifyCiphertext must have failed on type mismatch")
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("verifyCiphertext mustn't have verified given ciphertext")
+ }
+}
+
+func TrivialEncrypt(t *testing.T, fheUintType FheUintType) {
+ var value big.Int
+ switch fheUintType {
+ case FheUint8:
+ value = *big.NewInt(2)
+ case FheUint16:
+ value = *big.NewInt(4283)
+ case FheUint32:
+ value = *big.NewInt(1333337)
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ valueBytes := make([]byte, 32)
+ input := append(value.FillBytes(valueBytes), byte(fheUintType))
+ out, err := trivialEncryptRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ ct := new(tfheCiphertext).trivialEncrypt(value, fheUintType)
+ if common.BytesToHash(out) != ct.getHash() {
+ t.Fatalf("output hash in verifyCipertext is incorrect")
+ }
+ res := getVerifiedCiphertextFromEVM(environment, ct.getHash())
+ if res == nil {
+ t.Fatalf("verifyCiphertext must have verified given ciphertext")
+ }
+}
+
+func FheLibAdd(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs + rhs
+ signature := "fheAdd(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibSub(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs - rhs
+ signature := "fheSub(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibMul(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 3
+ rhs = 2
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs * rhs
+ signature := "fheMul(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibLe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ signature := "fheLe(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ // lhs <= rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs <= lhs
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ }
+}
+
+func FheLibLt(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ signature := "fheLt(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ // lhs < rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs < lhs
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ }
+}
+
+func FheLibEq(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ signature := "fheLt(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs == rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+}
+
+func FheLibGe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ signature := "fheGe(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs >= rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs >= lhs
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+ }
+}
+
+func FheLibGt(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ signature := "fheGt(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs > rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs > lhs
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+ }
+}
+
+func FheLibShl(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 2
+ case FheUint32:
+ lhs = 1333337
+ rhs = 3
+ }
+ expected := lhs << rhs
+ signature := "fheShl(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibShr(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 2
+ case FheUint32:
+ lhs = 1333337
+ rhs = 3
+ }
+ expected := lhs >> rhs
+ signature := "fheShr(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibNe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ signature := "fheNe(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs == rhs
+ input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+}
+
+func FheLibMin(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ signature := "fheMin(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != rhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != rhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs)
+ }
+ }
+}
+
+func FheLibMax(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ signature := "fheMax(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != lhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ input2 := toLibPrecompileInput(signature, false, rhsHash, lhsHash)
+ out, err = FheLibRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != lhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs)
+ }
+ }
+}
+
+func FheLibNeg(t *testing.T, fheUintType FheUintType) {
+ var pt, expected uint64
+ switch fheUintType {
+ case FheUint8:
+ pt = 2
+ expected = uint64(-uint8(pt))
+ case FheUint16:
+ pt = 4283
+ expected = uint64(-uint16(pt))
+ case FheUint32:
+ pt = 1333337
+ expected = uint64(-uint32(pt))
+ }
+
+ signature := "fheNeg(uint256)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).getHash()
+
+ input := toLibPrecompileInputNoScalar(signature, ptHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibNot(t *testing.T, fheUintType FheUintType) {
+ var pt, expected uint64
+ switch fheUintType {
+ case FheUint8:
+ pt = 2
+ expected = uint64(^uint8(pt))
+ case FheUint16:
+ pt = 4283
+ expected = uint64(^uint16(pt))
+ case FheUint32:
+ pt = 1333337
+ expected = uint64(^uint32(pt))
+ }
+
+ signature := "fheNot(uint256)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).getHash()
+
+ input := toLibPrecompileInputNoScalar(signature, ptHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheLibDiv(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 4
+ rhs = 2
+ case FheUint16:
+ lhs = 721
+ rhs = 1000
+ case FheUint32:
+ lhs = 137
+ rhs = 17
+ }
+ expected := lhs / rhs
+
+ signature := "fheDiv(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatal("Non scalar multiplication should fail")
+ }
+ }
+}
+
+func FheLibRem(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 7
+ rhs = 3
+ case FheUint16:
+ lhs = 721
+ rhs = 1000
+ case FheUint32:
+ lhs = 1337
+ rhs = 73
+ }
+ expected := lhs % rhs
+ signature := "fheRem(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatal("Non scalar remainder should fail")
+ }
+ }
+}
+
+func FheLibBitAnd(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs & rhs
+ signature := "fheBitAnd(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit and should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheLibBitOr(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs | rhs
+ signature := "fheBitOr(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit or should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheLibBitXor(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs ^ rhs
+ signature := "fheBitXor(uint256,uint256,bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit xor should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheLibRand(t *testing.T, fheUintType FheUintType) {
+ signature := "fheRand(bytes1)"
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ input := make([]byte, 0)
+ input = append(input, signatureBytes...)
+ input = append(input, byte(fheUintType))
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ } else if len(out) != 32 {
+ t.Fatalf("fheRand expected output len of 32, got %v", len(out))
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 1 {
+ t.Fatalf("fheRand expected 1 verified ciphertext")
+ }
+
+ hash := common.BytesToHash(out)
+ _, err = environment.FhevmData().verifiedCiphertexts[hash].ciphertext.decrypt()
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+}
+
+func LibTrivialEncrypt(t *testing.T, fheUintType FheUintType) {
+ var value big.Int
+ switch fheUintType {
+ case FheUint8:
+ value = *big.NewInt(2)
+ case FheUint16:
+ value = *big.NewInt(4283)
+ case FheUint32:
+ value = *big.NewInt(1333337)
+ }
+ signature := "trivialEncrypt(uint256,bytes1)"
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ valueBytes := make([]byte, 32)
+ input := make([]byte, 0)
+ input = append(input, signatureBytes...)
+ input = append(input, value.FillBytes(valueBytes)...)
+ input = append(input, byte(fheUintType))
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ ct := new(tfheCiphertext).trivialEncrypt(value, fheUintType)
+ if common.BytesToHash(out) != ct.getHash() {
+ t.Fatalf("output hash in verifyCipertext is incorrect")
+ }
+ res := getVerifiedCiphertextFromEVM(environment, ct.getHash())
+ if res == nil {
+ t.Fatalf("verifyCiphertext must have verified given ciphertext")
+ }
+}
+
+func LibDecrypt(t *testing.T, fheUintType FheUintType) {
+ var value uint64
+ switch fheUintType {
+ case FheUint8:
+ value = 2
+ case FheUint16:
+ value = 4283
+ case FheUint32:
+ value = 1333337
+ }
+ signature := "decrypt(uint256)"
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ input := make([]byte, 0)
+ hash := verifyCiphertextInTestMemory(environment, value, depth, fheUintType).getHash()
+ input = append(input, signatureBytes...)
+ input = append(input, hash.Bytes()...)
+ out, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ } else if len(out) != 32 {
+ t.Fatalf("decrypt expected output len of 32, got %v", len(out))
+ }
+ result := big.Int{}
+ result.SetBytes(out)
+ if result.Uint64() != value {
+ t.Fatalf("decrypt result not equal to value, result %v != value %v", result.Uint64(), value)
+ }
+}
+
+func TestLibVerifyCiphertextInvalidType(t *testing.T) {
+ signature := "verifyCiphertext(bytes)"
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ invalidType := FheUintType(255)
+ input := make([]byte, 0)
+ input = append(input, signatureBytes...)
+ compact := encryptAndSerializeCompact(0, FheUint32)
+ input = append(input, compact...)
+ input = append(input, byte(invalidType))
+ _, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err == nil {
+ t.Fatalf("verifyCiphertext must have failed on invalid ciphertext type")
+ }
+
+ if !strings.Contains(err.Error(), "ciphertext type is invalid") {
+ t.Fatalf("Unexpected test error: %s", err.Error())
+ }
+}
+
+func TestLibReencrypt(t *testing.T) {
+ signature := "reencrypt(uint256,uint256)"
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ environment.ethCall = true
+ toEncrypt := 7
+ fheUintType := FheUint8
+ encCiphertext := verifyCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).getHash()
+ addr := common.Address{}
+ readOnly := false
+ input := make([]byte, 0)
+ input = append(input, signatureBytes...)
+ input = append(input, encCiphertext.Bytes()...)
+ // just append twice not to generate public key
+ input = append(input, encCiphertext.Bytes()...)
+ _, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf("Reencrypt error: %s", err.Error())
+ }
+}
+
+func TestLibCast(t *testing.T) {
+ signature := "cast(uint256,bytes1)"
+ hashRes := crypto.Keccak256([]byte(signature))
+ signatureBytes := hashRes[0:4]
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ environment.ethCall = true
+ toEncrypt := 7
+ fheUintType := FheUint8
+ encCiphertext := verifyCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).getHash()
+ addr := common.Address{}
+ readOnly := false
+ input := make([]byte, 0)
+ input = append(input, signatureBytes...)
+ input = append(input, encCiphertext.Bytes()...)
+ input = append(input, byte(FheUint32))
+ _, err := FheLibRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf("Reencrypt error: %s", err.Error())
+ }
+}
+
+func FheAdd(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs + rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheAddRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheSub(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs - rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheSubRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheMul(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 169
+ rhs = 5
+ case FheUint32:
+ lhs = 137
+ rhs = 17
+ }
+ expected := lhs * rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheMulRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheDiv(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 4
+ rhs = 2
+ case FheUint16:
+ lhs = 721
+ rhs = 1000
+ case FheUint32:
+ lhs = 137
+ rhs = 17
+ }
+ expected := lhs / rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheDivRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatal("Non scalar multiplication should fail")
+ }
+ }
+}
+
+func FheRem(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 9
+ rhs = 5
+ case FheUint16:
+ lhs = 1773
+ rhs = 523
+ case FheUint32:
+ lhs = 123765
+ rhs = 2179
+ }
+ expected := lhs % rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheRemRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ } else {
+ if err == nil {
+ t.Fatal("Non scalar remainder should fail")
+ }
+ }
+}
+
+func FheBitAnd(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs & rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheBitAndRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit and should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheBitOr(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs | rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheBitOrRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit or should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheBitXor(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ expected := lhs ^ rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheBitXorRun(environment, addr, addr, input, readOnly)
+ if scalar {
+ if err == nil {
+ t.Fatalf("scalar bit xor should have failed")
+ }
+ } else {
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+ }
+}
+
+func FheShl(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 2
+ case FheUint32:
+ lhs = 1333337
+ rhs = 3
+ }
+ expected := lhs << rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheShlRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheShr(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 2
+ case FheUint32:
+ lhs = 1333337
+ rhs = 3
+ }
+ expected := lhs >> rhs
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheShrRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheEq(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs == rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheEqRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+}
+
+func FheNe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs == rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheNeRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+}
+
+func FheGe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs >= rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheGeRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs >= lhs
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheGeRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+ }
+}
+
+func FheGt(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+ // lhs > rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheGtRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs > lhs
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheGtRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+ }
+}
+
+func FheLe(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ // lhs <= rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheLeRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs <= lhs
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheLeRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ }
+}
+
+func FheLt(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ // lhs < rhs
+ input1 := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheLtRun(environment, addr, addr, input1, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 0 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ // rhs < lhs
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheLtRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != 1 {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1)
+ }
+ }
+}
+
+func FheMin(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheMinRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != rhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheMinRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != rhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs)
+ }
+ }
+}
+
+func FheMax(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var lhs, rhs uint64
+ switch fheUintType {
+ case FheUint8:
+ lhs = 2
+ rhs = 1
+ case FheUint16:
+ lhs = 4283
+ rhs = 1337
+ case FheUint32:
+ lhs = 1333337
+ rhs = 133337
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).getHash()
+ var rhsHash common.Hash
+ if scalar {
+ rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes())
+ } else {
+ rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).getHash()
+ }
+
+ input := toPrecompileInput(scalar, lhsHash, rhsHash)
+ out, err := fheMaxRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != lhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs)
+ }
+
+ // Inverting operands is only possible in the non scalar case as scalar
+ // operators expect the scalar to be on the rhs.
+ if !scalar {
+ input2 := toPrecompileInput(false, rhsHash, lhsHash)
+ out, err = fheMaxRun(environment, addr, addr, input2, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err = res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != lhs {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs)
+ }
+ }
+}
+
+func FheNeg(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var pt, expected uint64
+ switch fheUintType {
+ case FheUint8:
+ pt = 2
+ expected = uint64(-uint8(pt))
+ case FheUint16:
+ pt = 4283
+ expected = uint64(-uint16(pt))
+ case FheUint32:
+ pt = 1333337
+ expected = uint64(-uint32(pt))
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).getHash()
+
+ input := make([]byte, 0)
+ input = append(input, ptHash.Bytes()...)
+ out, err := fheNegRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func FheNot(t *testing.T, fheUintType FheUintType, scalar bool) {
+ var pt, expected uint64
+ switch fheUintType {
+ case FheUint8:
+ pt = 2
+ expected = uint64(^uint8(pt))
+ case FheUint16:
+ pt = 4283
+ expected = uint64(^uint16(pt))
+ case FheUint32:
+ pt = 1333337
+ expected = uint64(^uint32(pt))
+ }
+
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).getHash()
+
+ input := make([]byte, 0)
+ input = append(input, ptHash.Bytes()...)
+ out, err := fheNotRun(environment, addr, addr, input, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out))
+ if res == nil {
+ t.Fatalf("output ciphertext is not found in verifiedCiphertexts")
+ }
+ decrypted, err := res.ciphertext.decrypt()
+ if err != nil || decrypted.Uint64() != expected {
+ t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected)
+ }
+}
+
+func Decrypt(t *testing.T, fheUintType FheUintType) {
+ var value uint64
+ switch fheUintType {
+ case FheUint8:
+ value = 2
+ case FheUint16:
+ value = 4283
+ case FheUint32:
+ value = 1333337
+ }
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ hash := verifyCiphertextInTestMemory(environment, value, depth, fheUintType).getHash()
+ out, err := decryptRun(environment, addr, addr, hash.Bytes(), readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ } else if len(out) != 32 {
+ t.Fatalf("decrypt expected output len of 32, got %v", len(out))
+ }
+ result := big.Int{}
+ result.SetBytes(out)
+ if result.Uint64() != value {
+ t.Fatalf("decrypt result not equal to value, result %v != value %v", result.Uint64(), value)
+ }
+}
+
+func FheRand(t *testing.T, fheUintType FheUintType) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ out, err := fheRandRun(environment, addr, addr, []byte{byte(fheUintType)}, readOnly)
+ if err != nil {
+ t.Fatalf(err.Error())
+ } else if len(out) != 32 {
+ t.Fatalf("fheRand expected output len of 32, got %v", len(out))
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 1 {
+ t.Fatalf("fheRand expected 1 verified ciphertext")
+ }
+
+ hash := common.BytesToHash(out)
+ _, err = environment.FhevmData().verifiedCiphertexts[hash].ciphertext.decrypt()
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+}
+
+func TestVerifyCiphertextInvalidType(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ invalidType := FheUintType(255)
+ compact := encryptAndSerializeCompact(0, FheUint32)
+ input := append(compact, byte(invalidType))
+ _, err := verifyCiphertextRun(environment, addr, addr, input, readOnly)
+ if err == nil {
+ t.Fatalf("verifyCiphertext must have failed on invalid ciphertext type")
+ }
+}
+
+func TestTrivialEncryptInvalidType(t *testing.T) {
+ // TODO: maybe trivialEncryptRun shouldn't panic but return an error?
+ defer func() {
+ if r := recover(); r == nil {
+ t.Fatalf("trivialEncrypt must have failed (panic) on invalid ciphertext type")
+ }
+ }()
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ invalidType := FheUintType(255)
+ input := make([]byte, 32)
+ input = append(input, byte(invalidType))
+ trivialEncryptRun(environment, addr, addr, input, readOnly)
+}
+
+func TestCastInvalidType(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ invalidType := FheUintType(255)
+ hash := verifyCiphertextInTestMemory(environment, 1, depth, FheUint8).getHash()
+ input := make([]byte, 0)
+ input = append(input, hash.Bytes()...)
+ input = append(input, byte(invalidType))
+ _, err := castRun(environment, addr, addr, input, readOnly)
+ if err == nil {
+ t.Fatalf("cast must have failed on invalid ciphertext type")
+ }
+}
+
+func TestVerifyCiphertextInvalidSize(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ ctType := FheUint32
+ compact := encryptAndSerializeCompact(0, ctType)
+ input := append(compact[:len(compact)-1], byte(ctType))
+ _, err := verifyCiphertextRun(environment, addr, addr, input, readOnly)
+ if err == nil {
+ t.Fatalf("verifyCiphertext must have failed on invalid ciphertext size")
+ }
+}
+
+func TestVerifyCiphertext8(t *testing.T) {
+ VerifyCiphertext(t, FheUint8)
+}
+
+func TestVerifyCiphertext16(t *testing.T) {
+ VerifyCiphertext(t, FheUint16)
+}
+
+func TestVerifyCiphertext32(t *testing.T) {
+ VerifyCiphertext(t, FheUint32)
+}
+
+func TestTrivialEncrypt8(t *testing.T) {
+ TrivialEncrypt(t, FheUint8)
+}
+
+func TestTrivialEncrypt16(t *testing.T) {
+ TrivialEncrypt(t, FheUint16)
+}
+
+func TestTrivialEncrypt32(t *testing.T) {
+ TrivialEncrypt(t, FheUint32)
+}
+
+func TestVerifyCiphertext8BadType(t *testing.T) {
+ VerifyCiphertextBadType(t, FheUint8, FheUint16)
+ VerifyCiphertextBadType(t, FheUint8, FheUint32)
+}
+
+func TestVerifyCiphertext16BadType(t *testing.T) {
+ VerifyCiphertextBadType(t, FheUint16, FheUint8)
+ VerifyCiphertextBadType(t, FheUint16, FheUint32)
+}
+
+func TestVerifyCiphertext32BadType(t *testing.T) {
+ VerifyCiphertextBadType(t, FheUint32, FheUint8)
+ VerifyCiphertextBadType(t, FheUint32, FheUint16)
+}
+
+func TestVerifyCiphertextBadCiphertext(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ _, err := verifyCiphertextRun(environment, addr, addr, make([]byte, 10), readOnly)
+ if err == nil {
+ t.Fatalf("verifyCiphertext must fail on bad ciphertext input")
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("verifyCiphertext mustn't have verified given ciphertext")
+ }
+}
+
+func TestFheLibAdd8(t *testing.T) {
+ FheLibAdd(t, FheUint8, false)
+}
+
+func TestFheLibSub8(t *testing.T) {
+ FheLibSub(t, FheUint8, false)
+}
+
+func TestFheLibMul8(t *testing.T) {
+ FheLibMul(t, FheUint8, false)
+}
+
+func TestFheLibLe8(t *testing.T) {
+ FheLibLe(t, FheUint8, false)
+}
+
+func TestFheLibLt8(t *testing.T) {
+ FheLibLt(t, FheUint8, false)
+}
+
+func TestFheLibEq8(t *testing.T) {
+ FheLibEq(t, FheUint8, false)
+}
+
+func TestFheLibGe8(t *testing.T) {
+ FheLibGe(t, FheUint8, false)
+}
+
+func TestFheLibGt8(t *testing.T) {
+ FheLibGt(t, FheUint8, false)
+}
+
+func TestFheLibShl8(t *testing.T) {
+ FheLibShl(t, FheUint8, false)
+}
+
+func TestFheLibShr8(t *testing.T) {
+ FheLibShr(t, FheUint8, false)
+}
+
+func TestFheLibNe8(t *testing.T) {
+ FheLibNe(t, FheUint8, false)
+}
+
+func TestFheLibMin8(t *testing.T) {
+ FheLibMin(t, FheUint8, false)
+}
+
+func TestFheLibMax8(t *testing.T) {
+ FheLibMax(t, FheUint8, false)
+}
+
+func TestFheLibNeg8(t *testing.T) {
+ FheLibNeg(t, FheUint8)
+}
+
+func TestFheLibNot8(t *testing.T) {
+ FheLibNot(t, FheUint8)
+}
+
+func TestFheLibDiv8(t *testing.T) {
+ FheLibDiv(t, FheUint8, true)
+}
+
+func TestFheLibRem8(t *testing.T) {
+ FheLibRem(t, FheUint8, true)
+}
+
+func TestFheLibBitAnd8(t *testing.T) {
+ FheLibBitAnd(t, FheUint8, false)
+}
+
+func TestFheLibBitOr8(t *testing.T) {
+ FheLibBitOr(t, FheUint8, false)
+}
+
+func TestFheLibBitXor8(t *testing.T) {
+ FheLibBitXor(t, FheUint8, false)
+}
+
+func TestFheLibRand8(t *testing.T) {
+ FheLibRand(t, FheUint8)
+}
+
+func TestFheLibTrivialEncrypt8(t *testing.T) {
+ LibTrivialEncrypt(t, FheUint8)
+}
+
+func TestLibDecrypt8(t *testing.T) {
+ LibDecrypt(t, FheUint8)
+}
+
+func TestFheAdd8(t *testing.T) {
+ FheAdd(t, FheUint8, false)
+}
+
+func TestFheAdd16(t *testing.T) {
+ FheAdd(t, FheUint16, false)
+}
+
+func TestFheAdd32(t *testing.T) {
+ FheAdd(t, FheUint32, false)
+}
+
+func TestFheScalarAdd8(t *testing.T) {
+ FheAdd(t, FheUint8, true)
+}
+
+func TestFheScalarAdd16(t *testing.T) {
+ FheAdd(t, FheUint16, true)
+}
+
+func TestFheScalarAdd32(t *testing.T) {
+ FheAdd(t, FheUint32, true)
+}
+
+func TestFheSub8(t *testing.T) {
+ FheSub(t, FheUint8, false)
+}
+
+func TestFheSub16(t *testing.T) {
+ FheSub(t, FheUint16, false)
+}
+
+func TestFheSub32(t *testing.T) {
+ FheSub(t, FheUint32, false)
+}
+
+func TestFheScalarSub8(t *testing.T) {
+ FheSub(t, FheUint8, true)
+}
+
+func TestFheScalarSub16(t *testing.T) {
+ FheSub(t, FheUint16, true)
+}
+
+func TestFheScalarSub32(t *testing.T) {
+ FheSub(t, FheUint32, true)
+}
+
+func TestFheMul8(t *testing.T) {
+ FheMul(t, FheUint8, false)
+}
+
+func TestFheMul16(t *testing.T) {
+ FheMul(t, FheUint16, false)
+}
+
+func TestFheMul32(t *testing.T) {
+ FheMul(t, FheUint32, false)
+}
+
+func TestFheScalarMul8(t *testing.T) {
+ FheMul(t, FheUint8, true)
+}
+
+func TestFheScalarMul16(t *testing.T) {
+ FheMul(t, FheUint16, true)
+}
+
+func TestFheScalarMul32(t *testing.T) {
+ FheMul(t, FheUint32, true)
+}
+
+func TestFheDiv8(t *testing.T) {
+ FheDiv(t, FheUint8, false)
+}
+
+func TestFheDiv16(t *testing.T) {
+ FheDiv(t, FheUint16, false)
+}
+
+func TestFheDiv32(t *testing.T) {
+ FheDiv(t, FheUint32, false)
+}
+
+func TestFheScalarDiv8(t *testing.T) {
+ FheDiv(t, FheUint8, true)
+}
+
+func TestFheScalarDiv16(t *testing.T) {
+ FheDiv(t, FheUint16, true)
+}
+
+func TestFheScalarDiv32(t *testing.T) {
+ FheDiv(t, FheUint32, true)
+}
+
+func TestFheRem8(t *testing.T) {
+ FheRem(t, FheUint8, false)
+}
+
+func TestFheRem16(t *testing.T) {
+ FheRem(t, FheUint16, false)
+}
+
+func TestFheRem32(t *testing.T) {
+ FheRem(t, FheUint32, false)
+}
+
+func TestFheScalarRem8(t *testing.T) {
+ FheRem(t, FheUint8, true)
+}
+
+func TestFheScalarRem16(t *testing.T) {
+ FheRem(t, FheUint16, true)
+}
+
+func TestFheScalarRem32(t *testing.T) {
+ FheRem(t, FheUint32, true)
+}
+
+func TestFheBitAnd8(t *testing.T) {
+ FheBitAnd(t, FheUint8, false)
+}
+
+func TestFheBitAnd16(t *testing.T) {
+ FheBitAnd(t, FheUint16, false)
+}
+
+func TestFheBitAnd32(t *testing.T) {
+ FheBitAnd(t, FheUint32, false)
+}
+
+func TestFheScalarBitAnd8(t *testing.T) {
+ FheBitAnd(t, FheUint8, true)
+}
+
+func TestFheScalarBitAnd16(t *testing.T) {
+ FheBitAnd(t, FheUint16, true)
+}
+
+func TestFheScalarBitAnd32(t *testing.T) {
+ FheBitAnd(t, FheUint32, true)
+}
+
+func TestFheBitOr8(t *testing.T) {
+ FheBitOr(t, FheUint8, false)
+}
+
+func TestFheBitOr16(t *testing.T) {
+ FheBitOr(t, FheUint16, false)
+}
+
+func TestFheBitOr32(t *testing.T) {
+ FheBitOr(t, FheUint32, false)
+}
+
+func TestFheScalarBitOr8(t *testing.T) {
+ FheBitOr(t, FheUint8, true)
+}
+
+func TestFheScalarBitOr16(t *testing.T) {
+ FheBitOr(t, FheUint16, true)
+}
+
+func TestFheScalarBitOr32(t *testing.T) {
+ FheBitOr(t, FheUint32, true)
+}
+
+func TestFheBitXor8(t *testing.T) {
+ FheBitXor(t, FheUint8, false)
+}
+
+func TestFheBitXor16(t *testing.T) {
+ FheBitXor(t, FheUint16, false)
+}
+
+func TestFheBitXor32(t *testing.T) {
+ FheBitXor(t, FheUint32, false)
+}
+
+func TestFheScalarBitXor8(t *testing.T) {
+ FheBitXor(t, FheUint8, true)
+}
+
+func TestFheScalarBitXor16(t *testing.T) {
+ FheBitXor(t, FheUint16, true)
+}
+
+func TestFheScalarBitXor32(t *testing.T) {
+ FheBitXor(t, FheUint32, true)
+}
+
+func TestFheShl8(t *testing.T) {
+ FheShl(t, FheUint8, false)
+}
+
+func TestFheShl16(t *testing.T) {
+ FheShl(t, FheUint16, false)
+}
+
+func TestFheShl32(t *testing.T) {
+ FheShl(t, FheUint32, false)
+}
+
+func TestFheScalarShl8(t *testing.T) {
+ FheShl(t, FheUint8, true)
+}
+
+func TestFheScalarShl16(t *testing.T) {
+ FheShl(t, FheUint16, true)
+}
+
+func TestFheScalarShl32(t *testing.T) {
+ FheShl(t, FheUint32, true)
+}
+
+func TestFheShr8(t *testing.T) {
+ FheShr(t, FheUint8, false)
+}
+
+func TestFheShr16(t *testing.T) {
+ FheShr(t, FheUint16, false)
+}
+
+func TestFheShr32(t *testing.T) {
+ FheShr(t, FheUint32, false)
+}
+
+func TestFheScalarShr8(t *testing.T) {
+ FheShr(t, FheUint8, true)
+}
+
+func TestFheScalarShr16(t *testing.T) {
+ FheShr(t, FheUint16, true)
+}
+
+func TestFheScalarShr32(t *testing.T) {
+ FheShr(t, FheUint32, true)
+}
+
+func TestFheEq8(t *testing.T) {
+ FheEq(t, FheUint8, false)
+}
+
+func TestFheEq16(t *testing.T) {
+ FheEq(t, FheUint16, false)
+}
+
+func TestFheEq32(t *testing.T) {
+ FheEq(t, FheUint32, false)
+}
+
+func TestFheScalarEq8(t *testing.T) {
+ FheEq(t, FheUint8, true)
+}
+
+func TestFheScalarEq16(t *testing.T) {
+ FheEq(t, FheUint16, true)
+}
+
+func TestFheScalarEq32(t *testing.T) {
+ FheEq(t, FheUint32, true)
+}
+
+func TestFheNe8(t *testing.T) {
+ FheNe(t, FheUint8, false)
+}
+
+func TestFheNe16(t *testing.T) {
+ FheNe(t, FheUint16, false)
+}
+
+func TestFheNe32(t *testing.T) {
+ FheNe(t, FheUint32, false)
+}
+
+func TestFheScalarNe8(t *testing.T) {
+ FheNe(t, FheUint8, true)
+}
+
+func TestFheScalarNe16(t *testing.T) {
+ FheNe(t, FheUint16, true)
+}
+
+func TestFheScalarNe32(t *testing.T) {
+ FheNe(t, FheUint32, true)
+}
+
+func TestFheGe8(t *testing.T) {
+ FheGe(t, FheUint8, false)
+}
+
+func TestFheGe16(t *testing.T) {
+ FheGe(t, FheUint16, false)
+}
+
+func TestFheGe32(t *testing.T) {
+ FheGe(t, FheUint32, false)
+}
+
+func TestFheScalarGe8(t *testing.T) {
+ FheGe(t, FheUint8, true)
+}
+
+func TestFheScalarGe16(t *testing.T) {
+ FheGe(t, FheUint16, true)
+}
+
+func TestFheScalarGe32(t *testing.T) {
+ FheGe(t, FheUint32, true)
+}
+
+func TestFheGt8(t *testing.T) {
+ FheGt(t, FheUint8, false)
+}
+
+func TestFheGt16(t *testing.T) {
+ FheGt(t, FheUint16, false)
+}
+
+func TestFheGt32(t *testing.T) {
+ FheGt(t, FheUint32, false)
+}
+
+func TestFheScalarGt8(t *testing.T) {
+ FheGt(t, FheUint8, true)
+}
+
+func TestFheScalarGt16(t *testing.T) {
+ FheGt(t, FheUint16, true)
+}
+
+func TestFheScalarGt32(t *testing.T) {
+ FheGt(t, FheUint32, true)
+}
+
+func TestFheLe8(t *testing.T) {
+ FheLe(t, FheUint8, false)
+}
+
+func TestFheLe16(t *testing.T) {
+ FheLe(t, FheUint16, false)
+}
+
+func TestFheLe32(t *testing.T) {
+ FheLe(t, FheUint32, false)
+}
+
+func TestFheScalarLe8(t *testing.T) {
+ FheLe(t, FheUint8, true)
+}
+
+func TestFheScalarLe16(t *testing.T) {
+ FheLe(t, FheUint16, true)
+}
+
+func TestFheScalarLe32(t *testing.T) {
+ FheLe(t, FheUint32, true)
+}
+
+func TestFheLt8(t *testing.T) {
+ FheLt(t, FheUint8, false)
+}
+
+func TestFheLt16(t *testing.T) {
+ FheLt(t, FheUint16, false)
+}
+
+func TestFheLt32(t *testing.T) {
+ FheLt(t, FheUint32, false)
+}
+
+func TestFheScalarLt8(t *testing.T) {
+ FheLt(t, FheUint8, true)
+}
+
+func TestFheScalarLt16(t *testing.T) {
+ FheLt(t, FheUint16, true)
+}
+
+func TestFheScalarLt32(t *testing.T) {
+ FheLt(t, FheUint32, true)
+}
+
+func TestFheMin8(t *testing.T) {
+ FheMin(t, FheUint8, false)
+}
+
+func TestFheMin16(t *testing.T) {
+ FheMin(t, FheUint16, false)
+}
+
+func TestFheMin32(t *testing.T) {
+ FheMin(t, FheUint32, false)
+}
+
+func TestFheScalarMin8(t *testing.T) {
+ FheMin(t, FheUint8, true)
+}
+
+func TestFheScalarMin16(t *testing.T) {
+ FheMin(t, FheUint16, true)
+}
+
+func TestFheScalarMin32(t *testing.T) {
+ FheMin(t, FheUint32, true)
+}
+
+func TestFheMax8(t *testing.T) {
+ FheMax(t, FheUint8, false)
+}
+
+func TestFheMax16(t *testing.T) {
+ FheMax(t, FheUint16, false)
+}
+
+func TestFheMax32(t *testing.T) {
+ FheMax(t, FheUint32, false)
+}
+
+func TestFheNeg8(t *testing.T) {
+ FheNeg(t, FheUint8, false)
+}
+
+func TestFheNeg16(t *testing.T) {
+ FheNeg(t, FheUint16, false)
+}
+
+func TestFheNeg32(t *testing.T) {
+ FheNeg(t, FheUint32, false)
+}
+
+func TestFheNot8(t *testing.T) {
+ FheNot(t, FheUint8, false)
+}
+
+func TestFheNot16(t *testing.T) {
+ FheNot(t, FheUint16, false)
+}
+
+func TestFheNot32(t *testing.T) {
+ FheNot(t, FheUint32, false)
+}
+
+func TestFheScalarMax8(t *testing.T) {
+ FheMax(t, FheUint8, true)
+}
+
+func TestFheScalarMax16(t *testing.T) {
+ FheMax(t, FheUint16, true)
+}
+
+func TestFheScalarMax32(t *testing.T) {
+ FheMax(t, FheUint32, true)
+}
+
+func TestDecrypt8(t *testing.T) {
+ Decrypt(t, FheUint8)
+}
+
+func TestDecrypt16(t *testing.T) {
+ Decrypt(t, FheUint16)
+}
+
+func TestDecrypt32(t *testing.T) {
+ Decrypt(t, FheUint32)
+}
+
+func TestFheRand8(t *testing.T) {
+ FheRand(t, FheUint8)
+}
+
+func TestFheRand16(t *testing.T) {
+ FheRand(t, FheUint16)
+}
+
+func TestFheRand32(t *testing.T) {
+ FheRand(t, FheUint32)
+}
+
+func TestUnknownCiphertextHandle(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ hash := verifyCiphertextInTestMemory(environment, 2, depth, FheUint8).getHash()
+
+ ct := getVerifiedCiphertext(environment, hash)
+ if ct == nil {
+ t.Fatalf("expected that ciphertext is verified")
+ }
+
+ // change the hash
+ hash[0]++
+ ct = getVerifiedCiphertext(environment, hash)
+ if ct != nil {
+ t.Fatalf("expected that ciphertext is not verified")
+ }
+}
+
+func TestCiphertextNotVerifiedWithoutReturn(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ environment.depth = 1
+ verifiedDepth := 2
+ hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, FheUint8).getHash()
+
+ ct := getVerifiedCiphertext(environment, hash)
+ if ct != nil {
+ t.Fatalf("expected that ciphertext is not verified")
+ }
+}
+
+func TestCiphertextNotAutomaticallyDelegated(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ environment.depth = 3
+ verifiedDepth := 2
+ hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, FheUint8).getHash()
+
+ ct := getVerifiedCiphertext(environment, hash)
+ if ct != nil {
+ t.Fatalf("expected that ciphertext is not verified at depth (%d)", environment.depth)
+ }
+}
+
+func TestCiphertextVerificationConditions(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ verifiedDepth := 2
+ hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, FheUint8).getHash()
+
+ environment.depth = verifiedDepth
+ ctPtr := getVerifiedCiphertext(environment, hash)
+ if ctPtr == nil {
+ t.Fatalf("expected that ciphertext is verified at verifiedDepth (%d)", verifiedDepth)
+ }
+
+ environment.depth = verifiedDepth + 1
+ ct := getVerifiedCiphertext(environment, hash)
+ if ct != nil {
+ t.Fatalf("expected that ciphertext is not verified at verifiedDepth + 1 (%d)", verifiedDepth+1)
+ }
+
+ environment.depth = verifiedDepth - 1
+ ct = getVerifiedCiphertext(environment, hash)
+ if ct != nil {
+ t.Fatalf("expected that ciphertext is not verified at verifiedDepth - 1 (%d)", verifiedDepth-1)
+ }
+}
+
+func TestFheRandInvalidInput(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ _, err := fheRandRun(environment, addr, addr, []byte{}, readOnly)
+ if err == nil {
+ t.Fatalf("fheRand expected failure on invalid type")
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("fheRand expected 0 verified ciphertexts on invalid input")
+ }
+}
+
+func TestFheRandInvalidType(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ addr := common.Address{}
+ readOnly := false
+ _, err := fheRandRun(environment, addr, addr, []byte{byte(254)}, readOnly)
+ if err == nil {
+ t.Fatalf("fheRand expected failure on invalid type")
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("fheRand expected 0 verified ciphertexts on invalid type")
+ }
+}
+
+func TestFheRandEthCall(t *testing.T) {
+ depth := 1
+ environment := newTestEVMEnvironment()
+ environment.depth = depth
+ environment.ethCall = true
+ addr := common.Address{}
+ readOnly := true
+ _, err := fheRandRun(environment, addr, addr, []byte{byte(FheUint8)}, readOnly)
+ if err == nil {
+ t.Fatalf("fheRand expected failure on EthCall")
+ }
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("fheRand expected 0 verified ciphertexts on EthCall")
+ }
+}
diff --git a/fhevm/instructions.go b/fhevm/instructions.go
index 643c104..f2a08a1 100644
--- a/fhevm/instructions.go
+++ b/fhevm/instructions.go
@@ -13,7 +13,7 @@ import (
fhevm_crypto "github.com/zama-ai/fhevm-go/crypto"
)
-var zero = uint256.NewInt(0).Bytes32()
+var zero = common.BytesToHash(uint256.NewInt(0).Bytes())
func newInt(buf []byte) *uint256.Int {
i := uint256.NewInt(0)
diff --git a/fhevm/instructions_test.go b/fhevm/instructions_test.go
new file mode 100644
index 0000000..efa2f23
--- /dev/null
+++ b/fhevm/instructions_test.go
@@ -0,0 +1,537 @@
+// Copyright 2014 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 fhevm
+
+import (
+ "bytes"
+ "math/big"
+ "sync"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/holiman/uint256"
+ fhevm_crypto "github.com/zama-ai/fhevm-go/crypto"
+)
+
+func init() {
+ // register errors from geth so that tests recognize them
+ RegisterErrors(
+ vm.ErrOutOfGas,
+ vm.ErrCodeStoreOutOfGas,
+ vm.ErrDepth,
+ vm.ErrInsufficientBalance,
+ vm.ErrContractAddressCollision,
+ vm.ErrExecutionReverted,
+ vm.ErrMaxInitCodeSizeExceeded,
+ vm.ErrMaxCodeSizeExceeded,
+ vm.ErrInvalidJump,
+ vm.ErrWriteProtection,
+ vm.ErrReturnDataOutOfBounds,
+ vm.ErrGasUintOverflow,
+ vm.ErrInvalidCode,
+ vm.ErrNonceUintOverflow,
+ nil,
+ nil,
+ nil,
+ )
+}
+
+func verifyCiphertextInTestMemory(environment EVMEnvironment, value uint64, depth int, t FheUintType) *tfheCiphertext {
+ // Simulate as if the ciphertext is compact and comes externally.
+ ser := encryptAndSerializeCompact(uint32(value), t)
+ ct := new(tfheCiphertext)
+ err := ct.deserializeCompact(ser, t)
+ if err != nil {
+ panic(err)
+ }
+ return verifyTfheCiphertextInTestMemory(environment, ct, depth)
+}
+
+func verifyTfheCiphertextInTestMemory(environment EVMEnvironment, ct *tfheCiphertext, depth int) *tfheCiphertext {
+ verifiedCiphertext := importCiphertextToEVMAtDepth(environment, ct, depth)
+ return verifiedCiphertext.ciphertext
+}
+
+// Implementation of some geth data structures used for testing
+
+var stackPool = sync.Pool{
+ New: func() interface{} {
+ return &TestStack{data: make([]uint256.Int, 0, 16)}
+ },
+}
+
+type TestStack struct {
+ data []uint256.Int
+}
+
+func newstack() *TestStack {
+ return stackPool.Get().(*TestStack)
+}
+
+// Data returns the underlying uint256.Int array.
+func (st *TestStack) Data() []uint256.Int {
+ return st.data
+}
+
+func (st *TestStack) push(d *uint256.Int) {
+ // NOTE push limit (1024) is checked in baseCheck
+ st.data = append(st.data, *d)
+}
+
+func (st *TestStack) pop() (ret uint256.Int) {
+ ret = st.data[len(st.data)-1]
+ st.data = st.data[:len(st.data)-1]
+ return
+}
+
+func (st *TestStack) len() int {
+ return len(st.data)
+}
+
+func (st *TestStack) peek() *uint256.Int {
+ return &st.data[st.len()-1]
+}
+
+// Back returns the n'th item in stack
+func (st *TestStack) Back(n int) *uint256.Int {
+ return &st.data[st.len()-n-1]
+}
+
+func (st *TestStack) Peek() *uint256.Int { return st.peek() }
+
+func (st *TestStack) Pop() uint256.Int { return st.pop() }
+
+type TestScopeContext struct {
+ Memory *vm.Memory
+ Stack *TestStack
+ Contract *vm.Contract
+}
+
+type TestScopeContextInterface interface {
+ ScopeContext
+ pushToStack(*uint256.Int)
+}
+
+func (scope *TestScopeContext) GetContract() Contract { return scope.Contract }
+func (scope *TestScopeContext) GetMemory() Memory { return scope.Memory }
+func (scope *TestScopeContext) GetStack() Stack { return scope.Stack }
+func (scope *TestScopeContext) pushToStack(v *uint256.Int) { scope.Stack.push(v) }
+
+type testContractAddress struct{}
+
+func (c testContractAddress) Address() common.Address {
+ return common.Address{}
+}
+
+type testCallerAddress struct{}
+
+func (c testCallerAddress) Address() common.Address {
+ addr := common.Address{}
+ addr[0]++
+ return addr
+}
+
+func newTestScopeConext() TestScopeContextInterface {
+ c := new(TestScopeContext)
+ c.Memory = vm.NewMemory()
+ c.Memory.Resize(uint64(expandedFheCiphertextSize[FheUint8]) * 3)
+ c.Stack = newstack()
+ c.Contract = vm.NewContract(testCallerAddress{}, testContractAddress{}, big.NewInt(10), 100000)
+ return c
+}
+
+func uint256FromBig(b *big.Int) *uint256.Int {
+ value, overflow := uint256.FromBig(b)
+ if overflow {
+ panic("overflow")
+ }
+ return value
+}
+
+type MockEVMEnvironment struct {
+ fhevmData *FhevmData
+ depth int
+ stateDb *state.StateDB
+ commit bool
+ ethCall bool
+ readOnly bool
+}
+
+func (environment *MockEVMEnvironment) GetState(addr common.Address, hash common.Hash) common.Hash {
+ return environment.stateDb.GetState(addr, hash)
+}
+
+func (environment *MockEVMEnvironment) SetState(addr common.Address, key common.Hash, value common.Hash) {
+ environment.stateDb.SetState(addr, key, value)
+}
+
+func (environment *MockEVMEnvironment) GetNonce(common.Address) uint64 {
+ return 0
+}
+
+func (environment *MockEVMEnvironment) AddBalance(addr common.Address, amount *big.Int) {
+ environment.stateDb.AddBalance(addr, amount)
+}
+
+func (environment *MockEVMEnvironment) GetBalance(addr common.Address) *big.Int {
+ return environment.stateDb.GetBalance(addr)
+}
+
+func (environment *MockEVMEnvironment) Suicide(addr common.Address) bool {
+ return environment.stateDb.Suicide(addr)
+}
+
+func (environment *MockEVMEnvironment) GetDepth() int {
+ return environment.depth
+}
+
+func (environment *MockEVMEnvironment) GetLogger() Logger {
+ return &DefaultLogger{}
+}
+
+func (environment *MockEVMEnvironment) IsCommitting() bool {
+ return environment.commit
+}
+
+func (environment *MockEVMEnvironment) IsEthCall() bool {
+ return environment.ethCall
+}
+
+func (environment *MockEVMEnvironment) IsReadOnly() bool {
+ return environment.readOnly
+}
+
+func (environment *MockEVMEnvironment) CreateContract(caller common.Address, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
+ return make([]byte, 0), common.Address{}, 0, nil
+}
+
+func (environment *MockEVMEnvironment) CreateContract2(caller common.Address, code []byte, codeHash common.Hash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
+ return make([]byte, 0), common.Address{}, 0, nil
+}
+
+func (environment *MockEVMEnvironment) FhevmData() *FhevmData {
+ return environment.fhevmData
+}
+
+func (environment *MockEVMEnvironment) FhevmParams() *FhevmParams {
+ return &FhevmParams{}
+}
+
+func (environment *MockEVMEnvironment) EVMEnvironment() EVMEnvironment {
+ return environment
+}
+
+func newTestEVMEnvironment() *MockEVMEnvironment {
+ fhevmData := NewFhevmData()
+ db := rawdb.NewMemoryDatabase()
+ state, _ := state.New(common.Hash{}, state.NewDatabase(db), nil)
+ return &MockEVMEnvironment{fhevmData: &fhevmData, stateDb: state, commit: true}
+}
+
+func TestProtectedStorageSstoreSload(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ depth := 1
+ environment.depth = depth
+ ct := verifyCiphertextInTestMemory(environment, 2, depth, FheUint32)
+ ctHash := ct.getHash()
+ scope := newTestScopeConext()
+ loc := uint256.NewInt(10)
+ value := uint256FromBig(ctHash.Big())
+
+ // Setup and call SSTORE - it requires a location and a value to set there.
+ scope.pushToStack(value)
+ scope.pushToStack(loc)
+ _, err := OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Clear the verified ciphertexts.
+ environment.FhevmData().verifiedCiphertexts = make(map[common.Hash]*verifiedCiphertext)
+
+ // Setup and call SLOAD - it requires a location to load.
+ scope.pushToStack(loc)
+ _, err = OpSload(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Expect the ciphertext is verified after SLOAD.
+ ctAfterSload := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ctAfterSload == nil {
+ t.Fatalf("expected ciphertext is verified after sload")
+ }
+ if !bytes.Equal(ct.serialize(), ctAfterSload.ciphertext.serialize()) {
+ t.Fatalf("expected ciphertext after sload is the same as original")
+ }
+}
+
+func TestProtectedStorageGarbageCollectionNoFlaggedLocation(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ depth := 1
+ environment.depth = depth
+ ctHash := verifyCiphertextInTestMemory(environment, 2, depth, FheUint8).getHash()
+ scope := newTestScopeConext()
+ loc := uint256.NewInt(10)
+ locHash := common.BytesToHash(loc.Bytes())
+ value := uint256FromBig(ctHash.Big())
+ protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address())
+
+ // Persist the ciphertext in protected storage.
+ scope.pushToStack(value)
+ scope.pushToStack(loc)
+ _, err := OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Set location flag to zero, such that garbage collection doesn't happen.
+ flagHandleLocation := crypto.Keccak256Hash(crypto.Keccak256Hash(locHash.Bytes()).Bytes())
+ environment.SetState(protectedStorage, flagHandleLocation, zero)
+
+ // Overwrite the ciphertext handle with 0.
+ scope.pushToStack(uint256.NewInt(0))
+ scope.pushToStack(loc)
+ _, err = OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Verify that garbage collection hasn't happened.
+ metadata := ciphertextMetadata{}
+ metadataKey := crypto.Keccak256Hash(ctHash.Bytes())
+ metadata.deserialize(environment.GetState(protectedStorage, metadataKey))
+ slot := uint256FromBig(metadataKey.Big())
+ slot = slot.AddUint64(slot, 1)
+ foundNonZero := false
+ for i := uint64(0); i < metadata.length; i++ {
+ res := environment.GetState(protectedStorage, common.BytesToHash(slot.Bytes()))
+ if !bytes.Equal(res.Bytes(), zero.Bytes()) {
+ foundNonZero = true
+ break
+ }
+ slot = slot.AddUint64(slot, i)
+ }
+ if !foundNonZero {
+ t.Fatalf("garbage collection must not have happened")
+ }
+}
+
+func TestProtectedStorageGarbageCollection(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ depth := 1
+ environment.depth = depth
+ ctHash := verifyCiphertextInTestMemory(environment, 2, depth, FheUint8).getHash()
+ scope := newTestScopeConext()
+ loc := uint256.NewInt(10)
+ locHash := common.BytesToHash(loc.Bytes())
+ value := uint256FromBig(ctHash.Big())
+
+ // Persist the ciphertext in protected storage.
+ scope.pushToStack(value)
+ scope.pushToStack(loc)
+ _, err := OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Make sure ciphertext is persisted to protected storage.
+ protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address())
+ metadata := ciphertextMetadata{}
+ metadataKey := crypto.Keccak256Hash(ctHash.Bytes())
+ metadata.deserialize(environment.GetState(protectedStorage, metadataKey))
+ if metadata.refCount != 1 {
+ t.Fatalf("metadata.refcount of ciphertext is not 1")
+ }
+ if metadata.length != uint64(expandedFheCiphertextSize[FheUint8]) {
+ t.Fatalf("metadata.length (%v) != ciphertext len (%v)", metadata.length, uint64(expandedFheCiphertextSize[FheUint8]))
+ }
+ ciphertextLocationsToCheck := (metadata.length + 32 - 1) / 32
+ startOfCiphertext := newInt(metadataKey.Bytes())
+ startOfCiphertext.AddUint64(startOfCiphertext, 1)
+ ctIdx := startOfCiphertext
+ foundNonZero := false
+ for i := uint64(0); i < ciphertextLocationsToCheck; i++ {
+ c := environment.GetState(protectedStorage, common.BytesToHash(ctIdx.Bytes()))
+ u := uint256FromBig(c.Big())
+ if !u.IsZero() {
+ foundNonZero = true
+ break
+ }
+ ctIdx.AddUint64(startOfCiphertext, 1)
+ }
+ if !foundNonZero {
+ t.Fatalf("ciphertext is not persisted to protected storage")
+ }
+
+ // Check if the handle location is flagged in protected storage.
+ flagHandleLocation := crypto.Keccak256Hash(crypto.Keccak256Hash(locHash.Bytes()).Bytes())
+ foundFlag := environment.GetState(protectedStorage, flagHandleLocation)
+ if !bytes.Equal(foundFlag.Bytes(), flag.Bytes()) {
+ t.Fatalf("location flag not persisted to protected storage")
+ }
+
+ // Overwrite the ciphertext handle with 0.
+ scope.pushToStack(uint256.NewInt(0))
+ scope.pushToStack(loc)
+ _, err = OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Make sure the metadata and the ciphertext are garbage collected from protected storage.
+ protectedStorageIdx := newInt(metadataKey.Bytes())
+ foundNonZero = false
+ for i := uint64(0); i < ciphertextLocationsToCheck; i++ {
+ c := environment.GetState(protectedStorage, common.BytesToHash(protectedStorageIdx.Bytes()))
+ u := uint256FromBig(c.Big())
+ if !u.IsZero() {
+ foundNonZero = true
+ break
+ }
+ ctIdx.AddUint64(startOfCiphertext, 1)
+ }
+ if foundNonZero {
+ t.Fatalf("ciphertext is not garbage collected from protected storage")
+ }
+
+ // Make sure the flag location is zero.
+ foundFlag = environment.GetState(protectedStorage, flagHandleLocation)
+ if !bytes.Equal(foundFlag.Bytes(), zero.Bytes()) {
+ t.Fatalf("location flag is not set to zero on garbage collection")
+ }
+}
+
+func TestProtectedStorageSloadDoesNotVerifyNonHandle(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ scope := newTestScopeConext()
+ loc := uint256.NewInt(10)
+ value := uint256.NewInt(42)
+
+ scope.pushToStack(value)
+ scope.pushToStack(loc)
+ _, err := OpSstore(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ scope.pushToStack(loc)
+ _, err = OpSload(&pc, environment, scope)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ // Expect no verified ciphertexts.
+ if len(environment.FhevmData().verifiedCiphertexts) != 0 {
+ t.Fatalf("expected no verified ciphetexts")
+ }
+}
+
+func TestOpReturnDelegation(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ depth := 2
+ scope := newTestScopeConext()
+ ct := verifyCiphertextInTestMemory(environment, 2, depth, FheUint8)
+ ctHash := ct.getHash()
+
+ offset := uint256.NewInt(0)
+ length := uint256.NewInt(32)
+ scope.pushToStack(length)
+ scope.pushToStack(offset)
+ scope.GetMemory().Set(offset.Uint64(), length.Uint64(), ctHash[:])
+ environment.depth = depth
+ OpReturn(&pc, environment, scope)
+ environment.depth--
+ ctAfterOp := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ctAfterOp == nil {
+ t.Fatalf("expected ciphertext is still verified after the return op")
+ }
+ if !bytes.Equal(ct.serialize(), ctAfterOp.ciphertext.serialize()) {
+ t.Fatalf("expected ciphertext after the return op is the same as original")
+ }
+}
+
+func TestOpReturnUnverifyIfNotReturned(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ depth := 2
+ scope := newTestScopeConext()
+ ctHash := verifyCiphertextInTestMemory(environment, 2, depth, FheUint8).getHash()
+
+ offset := uint256.NewInt(0)
+ len := uint256.NewInt(32)
+ scope.pushToStack(len)
+ scope.pushToStack(offset)
+ // Set 0s as return.
+ scope.GetMemory().Set(offset.Uint64(), len.Uint64(), make([]byte, len.Uint64()))
+ environment.depth = depth
+ OpReturn(&pc, environment, scope)
+ environment.depth = depth - 1
+ ct := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ct != nil {
+ t.Fatalf("expected ciphertext is not verified after the return op")
+ }
+}
+
+func TestOpReturnDoesNotUnverifyIfNotVerified(t *testing.T) {
+ environment := newTestEVMEnvironment()
+ pc := uint64(0)
+ scope := newTestScopeConext()
+ ct := verifyCiphertextInTestMemory(environment, 2, 4, FheUint8)
+ ctHash := ct.getHash()
+
+ // Return from depth 3 to depth 2. However, ct is not verified at 3 and, hence, cannot
+ // be passed from 3 to 2. However, we expect that ct remains verified at 4.
+ offset := uint256.NewInt(0)
+ len := uint256.NewInt(32)
+ scope.pushToStack(len)
+ scope.pushToStack(offset)
+ scope.GetMemory().Set(offset.Uint64(), len.Uint64(), ctHash[:])
+ environment.depth = 3
+ OpReturn(&pc, environment, scope)
+ environment.depth--
+
+ ctAt2 := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ctAt2 != nil {
+ t.Fatalf("expected ciphertext is not verified at 2")
+ }
+ environment.depth = 3
+ ctAt3 := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ctAt3 != nil {
+ t.Fatalf("expected ciphertext is not verified at 3")
+ }
+ environment.depth = 4
+ ctAt4 := getVerifiedCiphertextFromEVM(environment, ctHash)
+ if ctAt4 == nil {
+ t.Fatalf("expected ciphertext is still verified at 4")
+ }
+ if !bytes.Equal(ct.serialize(), ctAt4.ciphertext.serialize()) {
+ t.Fatalf("expected ciphertext after the return op is the same as original")
+ }
+ if ctAt4.verifiedDepths.count() != 1 || !ctAt4.verifiedDepths.has(environment.depth) {
+ t.Fatalf("expected ciphertext to be verified at depth 4")
+ }
+}
diff --git a/go.mod b/go.mod
index cc6cc6e..98cc357 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,43 @@ require (
)
require (
+ github.com/DataDog/zstd v1.5.2 // indirect
+ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
+ github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
+ github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cockroachdb/errors v1.9.1 // indirect
+ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
+ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
+ github.com/cockroachdb/redact v1.1.3 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
+ github.com/getsentry/sentry-go v0.18.0 // indirect
+ github.com/go-ole/go-ole v1.2.1 // indirect
+ github.com/go-stack/stack v1.8.1 // indirect
+ github.com/gofrs/flock v0.8.1 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
+ github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
+ github.com/klauspost/compress v1.15.15 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/kr/text v0.2.0 // indirect
+ github.com/mattn/go-runewidth v0.0.9 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/prometheus/client_golang v1.14.0 // indirect
+ github.com/prometheus/client_model v0.3.0 // indirect
+ github.com/prometheus/common v0.39.0 // indirect
+ github.com/prometheus/procfs v0.9.0 // indirect
+ github.com/rogpeppe/go-internal v1.9.0 // indirect
+ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
+ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
+ github.com/tklauser/go-sysconf v0.3.5 // indirect
+ github.com/tklauser/numcpus v0.2.2 // indirect
+ golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/sys v0.7.0 // indirect
+ golang.org/x/text v0.8.0 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
)
diff --git a/go.sum b/go.sum
index 24cad07..f5ef0f5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,16 +1,438 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
+github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
+github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
+github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
+github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
+github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
+github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
+github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
+github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
+github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
+github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
+github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8=
+github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk=
+github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk=
+github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM=
+github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ=
+github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
+github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
+github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0=
github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs=
+github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
+github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
+github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
+github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
+github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
+github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
+github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
+github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
+github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
+github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
+github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
+github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
+github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
+github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8=
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
+github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
+github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
+github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
+github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
+github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
+github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
+github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
+github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
+github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
+github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
+github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
+github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
+github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
+github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
+github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
+github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
+github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
+github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
+github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
+github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI=
+github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y=
+github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
+github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
+github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
+github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
+github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
+github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
+github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
+github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
+github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
+golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
-golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
\ No newline at end of file
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
+google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
+gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
+gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=