diff --git a/Makefile b/Makefile index d83dff6..d26b514 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ build: build-tfhe-rs-capi test: build-tfhe-rs-capi cd fhevm && go test -v . +.PHONY: gasEstimation +gasEstimation: build-tfhe-rs-capi + cd fhevm && go test -count=1 -v . -run GasEstimation + .PHONY: build-tfhe-rs-capi build-tfhe-rs-capi: cd tfhe-rs && RUSTFLAGS="" make build_c_api_experimental_deterministic_fft \ diff --git a/fhevm/contracts_test.go b/fhevm/contracts_test.go index 7ee675c..3f46850 100644 --- a/fhevm/contracts_test.go +++ b/fhevm/contracts_test.go @@ -731,7 +731,7 @@ func FheLibShr(t *testing.T, fheUintType FheUintType, scalar bool) { rhs = 1 case FheUint16: lhs = 4283 - rhs = 2 + rhs = 3 case FheUint32: lhs = 1333337 rhs = 3 @@ -1597,7 +1597,7 @@ func FheMul(t *testing.T, fheUintType FheUintType, scalar bool) { switch fheUintType { case FheUint8: lhs = 2 - rhs = 1 + rhs = 3 case FheUint16: lhs = 169 rhs = 5 @@ -1637,14 +1637,14 @@ func FheDiv(t *testing.T, fheUintType FheUintType, scalar bool) { var lhs, rhs uint64 switch fheUintType { case FheUint8: - lhs = 4 - rhs = 2 + lhs = 6 + rhs = 7 case FheUint16: lhs = 721 - rhs = 1000 + rhs = 251 case FheUint32: lhs = 137 - rhs = 17 + rhs = 65521 } expected := lhs / rhs depth := 1 @@ -1917,7 +1917,7 @@ func FheShr(t *testing.T, fheUintType FheUintType, scalar bool) { rhs = 1 case FheUint16: lhs = 4283 - rhs = 2 + rhs = 3 case FheUint32: lhs = 1333337 rhs = 3 diff --git a/fhevm/gasEstimation_test.go b/fhevm/gasEstimation_test.go new file mode 100644 index 0000000..d747627 --- /dev/null +++ b/fhevm/gasEstimation_test.go @@ -0,0 +1,73 @@ +package fhevm + +import ( + "testing" + "time" +) + +type operation func(FheUintType) + +const numBenchmarkRuns = 5 + +func convertInGas(t *testing.T, name string, elapsed [numBenchmarkRuns]time.Duration) { + lowest := elapsed[0] + + // Find the lowest duration in the array + for i := 1; i < numBenchmarkRuns; i++ { + if elapsed[i] < lowest { + lowest = elapsed[i] + } + } + + gasUsed := int64(lowest) / 1000 // 1s = 1,000,000 gas + gasUsed = gasUsed / 7 * 10 // 0.7s = 1,000,000 gas + gasUsed = gasUsed / 1000 // Divide to round it + + t.Logf("%s in %s => %d", name, lowest, gasUsed*1000) +} + +func runTest(t *testing.T, name string, fn operation, bits string, fheUintType FheUintType) { + var elapsed [numBenchmarkRuns]time.Duration + n := 0 + for n < numBenchmarkRuns { + start := time.Now() + fn(fheUintType) + elapsed[n] = time.Since(start) + n += 1 + } + convertInGas(t, name+bits, elapsed) +} + +func estimateTests(t *testing.T, name string, fn operation) { + runTest(t, name, fn, "8", FheUint8) + runTest(t, name, fn, "16", FheUint16) + runTest(t, name, fn, "32", FheUint32) +} + +func TestGasEstimation(t *testing.T) { + estimateTests(t, "not", func(fheUintType FheUintType) { FheNot(t, fheUintType, false) }) + + estimateTests(t, "and", func(fheUintType FheUintType) { FheBitAnd(t, fheUintType, false) }) + + estimateTests(t, "eq", func(fheUintType FheUintType) { FheEq(t, fheUintType, false) }) + estimateTests(t, "ScalarEq", func(fheUintType FheUintType) { FheEq(t, fheUintType, true) }) + + estimateTests(t, "shr", func(fheUintType FheUintType) { FheShr(t, fheUintType, false) }) + estimateTests(t, "ScalarShr", func(fheUintType FheUintType) { FheShr(t, fheUintType, true) }) + + estimateTests(t, "min", func(fheUintType FheUintType) { FheMin(t, fheUintType, false) }) + estimateTests(t, "ScalarMin", func(fheUintType FheUintType) { FheMin(t, fheUintType, true) }) + + estimateTests(t, "add", func(fheUintType FheUintType) { FheAdd(t, fheUintType, false) }) + estimateTests(t, "ScalarAdd", func(fheUintType FheUintType) { FheAdd(t, fheUintType, true) }) + + estimateTests(t, "sub", func(fheUintType FheUintType) { FheSub(t, fheUintType, false) }) + estimateTests(t, "ScalarSub", func(fheUintType FheUintType) { FheSub(t, fheUintType, true) }) + + estimateTests(t, "mul", func(fheUintType FheUintType) { FheMul(t, fheUintType, false) }) + estimateTests(t, "ScalarMul", func(fheUintType FheUintType) { FheMul(t, fheUintType, true) }) + + estimateTests(t, "ScalarDiv", func(fheUintType FheUintType) { FheDiv(t, fheUintType, true) }) + + estimateTests(t, "IfThenElse", func(fheUintType FheUintType) { FheIfThenElse(t, fheUintType, 1) }) +}